[saods9] 01/07: New upstream+dfsg version 7.3b3
Ole Streicher
olebole-guest at alioth.debian.org
Thu Sep 26 12:24:24 UTC 2013
This is an automated email from the git hooks/post-receive script.
olebole-guest pushed a commit to branch debian
in repository saods9.
commit 8688b19575ce4aecd54f6027f4b998b09b3b3da5
Author: Ole Streicher <debian at liska.ath.cx>
Date: Thu Sep 26 10:55:30 2013 +0200
New upstream+dfsg version 7.3b3
---
Makefile | 269 +-
Makefile.macosx | 172 +
Makefile.unix | 102 +
Makefile.windows | 116 +
blt3.0.1/configure | 4 +-
blt3.0.1/src/bltUnixBitmap.c | 2 +
blt3.0.1/src/bltUnixPainter.c | 8 +-
blt3.0.1/src/bltUnixWindow.c | 10 +-
doc/release/r7.0.html | 10 +
ds9/Makefile | 404 +-
ds9/Makefile.macosx | 166 +
ds9/Makefile.unix | 226 +
ds9/Makefile.windows | 132 +
ds9/{ds9.C => ds9.macosx} | 137 +-
ds9/{ds9.C => ds9.unix} | 86 +-
ds9/{ds9.C => ds9.windows} | 122 +-
.../Contents/Info.plist | 2 +-
.../Contents/MacOS/ds9 | 0
.../Contents/PkgInfo | 0
.../Contents/Resources/App.icns | Bin 0 -> 47991 bytes
.../Resources/English.lproj/InfoPlist.strings | Bin 686 -> 686 bytes
.../Resources/English.lproj/main.nib/classes.nib | 0
.../Resources/English.lproj/main.nib/info.nib | 0
.../Resources/English.lproj/main.nib/objects.xib | 0
.../Contents/Resources/fits.icns | Bin 0 -> 48529 bytes
ds9/macosx/SAOImage DS9.app/Contents/Info.plist | 26 +-
ds9/win/ds9.rc | 2 +-
macosx/Makefile | 24 +-
macosx/macosxlib.h | 6 +-
macosx/{macosxlib.C => macosxlib.mm} | 7 -
{unix => macosx}/rotstr.h | 7 +-
macosx/rotstr.mm | 52 +
macosx/tkmacosx.h | 9 +-
macosx/{tkmacosx.C => tkmacosx.mm} | 108 +-
macosx/xxlib.C | 336 -
macosx/xxlib.h | 36 +-
macosx/xxlib.mm | 142 +
make.cygwin | 6 +-
make.darwin64x86lion | 10 +-
make.darwin64x86mountainlion | 12 +-
make.darwin64x86snowleopard | 10 +-
make.darwinx86lion | 11 +-
make.darwinx86mountainlion | 11 +-
make.darwinx86snowleopard | 11 +-
make.linux | 9 +-
make.linux64 | 8 +-
...darwinx86snowleopard => make.macosxmountainlion | 16 +-
make.macosxx86mountainlion | 27 -
make.pkgs | 10 +-
make.source | 1 +
notes.txt | 103 +-
saotk/colorbar/Makefile | 33 +-
saotk/colorbar/colorbarpseudocolor.C | 2 +-
saotk/colorbar/colorbarpseudocolor8.C | 189 -
saotk/colorbar/colorbarrgbtruecolor.C | 2 +-
saotk/colorbar/colorbarrgbtruecolor16.C | 4 +-
saotk/colorbar/colorbarrgbtruecolor24.C | 43 +-
saotk/colorbar/colorbarrgbtruecolor8.C | 4 +-
saotk/colorbar/colorbartrue.C | 2 +-
saotk/colorbar/colorbartruecolor.C | 2 +-
saotk/colorbar/colorbartruecolor16.C | 4 +-
saotk/colorbar/colorbartruecolor24.C | 16 +-
saotk/colorbar/colorbartruecolor8.C | 4 +-
saotk/colorbar/colortag.h | 4 +-
saotk/fitsy++/Makefile | 20 +-
saotk/fitsy++/alloc.C | 1 +
saotk/fitsy++/analysis.C | 4 +-
saotk/fitsy++/channel.C | 2 +
saotk/fitsy++/compress.C | 11 +-
saotk/fitsy++/compress.h | 4 +-
saotk/fitsy++/envi.C | 208 +-
saotk/fitsy++/envi.h | 20 +-
saotk/fitsy++/envilex.C | 670 +-
saotk/fitsy++/envilex.L | 3 +
saotk/fitsy++/enviparser.C | 548 +-
saotk/fitsy++/enviparser.H | 108 +-
saotk/fitsy++/enviparser.Y | 5 +
saotk/fitsy++/file.C | 78 +-
saotk/fitsy++/file.h | 22 +-
saotk/fitsy++/hist.C | 9 +-
saotk/fitsy++/hpx.C | 35 -
saotk/fitsy++/hpx.h | 8 +-
saotk/fitsy++/map.C | 14 +-
saotk/fitsy++/mapincr.C | 11 +-
saotk/fitsy++/nrrd.C | 183 +-
saotk/fitsy++/nrrd.h | 11 +-
saotk/fitsy++/nrrdgzip.C | 2 +-
saotk/fitsy++/nrrdparser.C | 11 +-
saotk/fitsy++/nrrdparser.Y | 1 -
saotk/fitsy++/outchannel.C | 2 +
saotk/fitsy++/outfile.C | 1 +
saotk/fitsy++/outfits.h | 2 -
saotk/fitsy++/parser.C | 251 +-
saotk/fitsy++/parser.Y | 6 +-
saotk/fitsy++/photo.C | 15 +-
saotk/fitsy++/photo.h | 2 +
saotk/fitsy++/savefits.C | 99 +-
saotk/fitsy++/smap.C | 12 +-
saotk/fitsy++/strm.C | 15 +-
saotk/fitsy++/var.C | 2 +
saotk/frame/Makefile | 34 +-
saotk/frame/annulus.C | 2 +
saotk/frame/base.C | 4 +-
saotk/frame/base.h | 4 +-
saotk/frame/basebox.C | 10 +-
saotk/frame/basebox.h | 11 +-
saotk/frame/basecommand.C | 2 +-
saotk/frame/baseellipse.C | 6 +-
saotk/frame/baseellipse.h | 11 +-
saotk/frame/baseline.C | 2 +
saotk/frame/basemarker.C | 2 +
saotk/frame/box.C | 2 +
saotk/frame/boxannulus.C | 2 +
saotk/frame/bpanda.C | 6 +-
saotk/frame/circle.C | 2 +
saotk/frame/colorscale.h | 3 -
saotk/frame/colorscalepseudo8.C | 112 -
saotk/frame/colorscalepseudo8.h | 91 -
saotk/frame/colorscalergb.h | 3 -
saotk/frame/colorscaletrue32.C | 6 +
saotk/frame/compass.C | 4 +-
saotk/frame/composite.C | 2 +
saotk/frame/context.C | 50 +-
saotk/frame/context.h | 1 -
saotk/frame/contour.h | 3 +
saotk/frame/cpanda.C | 2 +
saotk/frame/ellipse.C | 2 +
saotk/frame/ellipseannulus.C | 2 +
saotk/frame/epanda.C | 2 +
saotk/frame/fitscompress.C | 62 +-
saotk/frame/fitsenvi.C | 34 +-
saotk/frame/fitsimage.C | 50 +-
saotk/frame/fitsimage.h | 8 +-
saotk/frame/fitsmask.C | 4 +
saotk/frame/fitsmask.h | 1 -
saotk/frame/fitsnrrd.C | 20 +-
saotk/frame/fr3dcommand.C | 2 -
saotk/frame/frame3dbase.C | 8 +-
saotk/frame/frame3dtrue.C | 4 -
saotk/frame/frame3dtruecolor.C | 4 -
saotk/frame/framebase.C | 4 -
saotk/frame/framepseudo.C | 53 -
saotk/frame/framepseudo.h | 20 -
saotk/frame/framepseudocolor.C | 143 -
saotk/frame/framepseudocolor.h | 26 -
saotk/frame/framepseudocolor8.C | 167 -
saotk/frame/framepseudocolor8.h | 21 -
saotk/frame/framergb.C | 26 +-
saotk/frame/framergbtruecolor.C | 2 +-
saotk/frame/frametrue.C | 6 +-
saotk/frame/frametruecolor.C | 4 +-
saotk/frame/frblt.C | 88 +-
saotk/frame/frcommand.C | 2 +-
saotk/frame/grid.h | 2 -
saotk/frame/grid25d.h | 2 -
saotk/frame/grid2d.h | 2 -
saotk/frame/grid3d.h | 2 -
saotk/frame/line.C | 2 +
saotk/frame/marker.C | 15 +-
saotk/frame/marker.h | 19 +-
saotk/frame/point.C | 7 +-
saotk/frame/point.h | 9 +-
saotk/frame/polygon.C | 5 +-
saotk/frame/polygon.h | 12 +-
saotk/frame/projection.C | 2 +
saotk/frame/ruler.C | 4 +-
saotk/frame/segment.C | 2 +
saotk/frame/text.C | 14 +-
saotk/frame/vect.C | 2 +
saotk/list/Makefile | 20 +-
saotk/magnifier/Makefile | 31 +-
saotk/magnifier/magnifierpseudo.C | 107 -
saotk/magnifier/magnifierpseudo.h | 18 -
saotk/magnifier/magnifiertrue.C | 4 +-
saotk/panner/Makefile | 27 +-
saotk/panner/panner.C | 2 +-
saotk/panner/pannerpseudo.C | 104 -
saotk/panner/pannerpseudo.h | 19 -
saotk/panner/pannertrue.C | 5 +-
saotk/util/Makefile | 20 +-
saotk/util/grid25dbase.h | 2 -
saotk/util/grid2dbase.h | 2 -
saotk/util/gridbase.C | 9 +-
saotk/util/saotk.C | 21 +-
saotk/util/util.C | 4 -
saotk/util/util.h | 11 +-
saotk/vector/Makefile | 20 +-
saotk/vector/vector.C | 8 +-
saotk/vector/vector.h | 6 +-
saotk/vector/vector3d.C | 7 +-
saotk/vector/vector3d.h | 4 +-
saotk/vector/vectorold.h | 2 +-
saotk/widget/Makefile | 20 +-
saotk/widget/truecolor16.C | 18 +-
saotk/widget/truecolor24.C | 29 +-
saotk/widget/truecolor8.C | 18 +-
saotk/widget/widget.h | 1 -
src/3d.tcl | 1 -
src/Makefile | 9 +-
src/analysis.tcl | 2 +-
src/backup.tcl | 11 +-
src/bin.tcl | 1 -
src/buttons.tcl | 44 +-
src/catcmd.tcl | 13 +
src/catdialog.tcl | 2 +-
src/catsym.tcl | 2 +-
src/centroid.tcl | 1 -
src/colorbar.tcl | 146 +-
src/command.tcl | 2 +-
src/ds9.tcl | 156 +-
src/frame.tcl | 127 +-
src/group.tcl | 10 +-
src/hvsup.tcl | 3 +
src/layout.tcl | 24 +-
src/macosx.tcl | 33 +-
src/marker.tcl | 1 +
src/mask.tcl | 12 +-
src/mcolor.tcl | 7 +-
src/menu.tcl | 19 +-
src/mframe.tcl | 14 +-
src/mhelp.tcl | 42 +-
src/print.tcl | 52 +-
src/stdfbox.tcl | 83 +-
src/util.tcl | 36 +-
tests/parse.sh | 8 +-
tlt3.0/Makefile.in | 449 +
tlt3.0/aclocal.m4 | 96 +
tlt3.0/bltBase64.c | 285 +
tlt3.0/bltBase64.h | 39 +
tlt3.0/bltBgStyle.c | 2018 ++++
tlt3.0/bltBgStyle.h | 74 +
tlt3.0/bltBind.c | 776 ++
tlt3.0/bltBind.h | 120 +
blt3.0.1/src/bltUnixBitmap.c => tlt3.0/bltBitmap.c | 132 +-
tlt3.0/bltBitmap.h | 43 +
tlt3.0/bltChain.c | 520 +
tlt3.0/bltChain.h | 90 +
tlt3.0/bltConfig.c | 2024 ++++
tlt3.0/bltConfig.h | 326 +
tlt3.0/bltDBuffer.c | 323 +
tlt3.0/bltDBuffer.h | 92 +
tlt3.0/bltFont.h | 137 +
tlt3.0/bltGrAxis.c | 5564 ++++++++++
tlt3.0/bltGrAxis.h | 332 +
tlt3.0/bltGrBar.c | 2539 +++++
tlt3.0/bltGrElem.c | 2214 ++++
tlt3.0/bltGrElem.h | 251 +
tlt3.0/bltGrHairs.c | 535 +
tlt3.0/bltGrLegd.c | 2838 ++++++
tlt3.0/bltGrLegd.h | 60 +
tlt3.0/bltGrLine.c | 4798 +++++++++
tlt3.0/bltGrMarker.c | 4372 ++++++++
tlt3.0/bltGrMisc.c | 1005 ++
tlt3.0/bltGrPen.c | 760 ++
tlt3.0/bltGrPs.c | 709 ++
tlt3.0/bltGraph.c | 1762 ++++
tlt3.0/bltGraph.h | 698 ++
tlt3.0/bltHash.c | 1266 +++
tlt3.0/bltHash.h | 180 +
tlt3.0/bltImage.c | 156 +
tlt3.0/bltImage.h | 51 +
tlt3.0/bltInit.c | 123 +
tlt3.0/bltInt.c | 83 +
tlt3.0/bltInt.h | 331 +
tlt3.0/bltList.c | 558 +
tlt3.0/bltList.h | 116 +
tlt3.0/bltMath.h | 45 +
tlt3.0/bltNsUtil.c | 146 +
tlt3.0/bltNsUtil.h | 59 +
tlt3.0/bltOp.h | 37 +
tlt3.0/bltParse.c | 511 +
tlt3.0/bltParse.h | 47 +
tlt3.0/bltPool.c | 474 +
tlt3.0/bltPool.h | 23 +
tlt3.0/bltPs.c | 1328 +++
tlt3.0/bltPs.h | 210 +
tlt3.0/bltPsAfm.c | 1557 +++
tlt3.0/bltPsInt.h | 49 +
tlt3.0/bltSpline.c | 1287 +++
tlt3.0/bltSpline.h | 43 +
tlt3.0/bltSwitch.c | 538 +
tlt3.0/bltSwitch.h | 134 +
tlt3.0/bltText.c | 1320 +++
tlt3.0/bltText.h | 240 +
tlt3.0/bltUnixFont.c | 2658 +++++
tlt3.0/bltUnixWindow.c | 211 +
tlt3.0/bltUtil.c | 731 ++
tlt3.0/bltVecCmd.c | 2418 +++++
tlt3.0/bltVecInt.h | 250 +
tlt3.0/bltVecMath.c | 1897 ++++
tlt3.0/bltVector.c | 2794 +++++
tlt3.0/bltVector.h | 137 +
tlt3.0/bltWindow.c | 247 +
tlt3.0/bltWindow.h | 58 +
tlt3.0/configure |10699 ++++++++++++++++++++
tlt3.0/configure.in | 299 +
tlt3.0/doc/BLT.n | 153 +
tlt3.0/doc/barchart.n | 2236 ++++
tlt3.0/doc/graph.n | 2397 +++++
tlt3.0/doc/vector.n | 1130 +++
tlt3.0/library/afm/AvantGarde-Book.afm | 574 ++
tlt3.0/library/afm/AvantGarde-BookOblique.afm | 574 ++
tlt3.0/library/afm/AvantGarde-Demi.afm | 577 ++
tlt3.0/library/afm/AvantGarde-DemiOblique.afm | 577 ++
tlt3.0/library/afm/Bookman-Demi.afm | 416 +
tlt3.0/library/afm/Bookman-DemiItalic.afm | 418 +
tlt3.0/library/afm/Bookman-Light.afm | 408 +
tlt3.0/library/afm/Bookman-LightItalic.afm | 411 +
tlt3.0/library/afm/Courier-Bold.afm | 345 +
tlt3.0/library/afm/Courier-BoldOblique.afm | 345 +
tlt3.0/library/afm/Courier-Oblique.afm | 345 +
tlt3.0/library/afm/Courier.afm | 345 +
tlt3.0/library/afm/Helvetica-Bold.afm | 571 ++
tlt3.0/library/afm/Helvetica-BoldOblique.afm | 571 ++
tlt3.0/library/afm/Helvetica-Condensed-Bold.afm | 419 +
tlt3.0/library/afm/Helvetica-Condensed-BoldObl.afm | 419 +
tlt3.0/library/afm/Helvetica-Condensed-Oblique.afm | 421 +
tlt3.0/library/afm/Helvetica-Condensed.afm | 421 +
tlt3.0/library/afm/Helvetica-Narrow-Bold.afm | 571 ++
.../library/afm/Helvetica-Narrow-BoldOblique.afm | 571 ++
tlt3.0/library/afm/Helvetica-Narrow-Oblique.afm | 613 ++
tlt3.0/library/afm/Helvetica-Narrow.afm | 613 ++
tlt3.0/library/afm/Helvetica-Oblique.afm | 613 ++
tlt3.0/library/afm/Helvetica.afm | 613 ++
tlt3.0/library/afm/NewCenturySchlbk-Bold.afm | 473 +
tlt3.0/library/afm/NewCenturySchlbk-BoldItalic.afm | 603 ++
tlt3.0/library/afm/NewCenturySchlbk-Italic.afm | 537 +
tlt3.0/library/afm/NewCenturySchlbk-Roman.afm | 525 +
tlt3.0/library/afm/Palatino-Bold.afm | 435 +
tlt3.0/library/afm/Palatino-BoldItalic.afm | 442 +
tlt3.0/library/afm/Palatino-Italic.afm | 440 +
tlt3.0/library/afm/Palatino-Roman.afm | 446 +
tlt3.0/library/afm/Symbol.afm | 210 +
tlt3.0/library/afm/Times-Bold.afm | 649 ++
tlt3.0/library/afm/Times-BoldItalic.afm | 649 ++
tlt3.0/library/afm/Times-Italic.afm | 649 ++
tlt3.0/library/afm/Times-Roman.afm | 649 ++
tlt3.0/library/afm/ZapfChancery-MediumItalic.afm | 481 +
tlt3.0/library/afm/ZapfDingbats.afm | 223 +
tlt3.0/library/bltGraph.pro | 472 +
tlt3.0/library/graph.tcl | 840 ++
tlt3.0/pkgIndex.tcl.in | 5 +
tlt3.0/tclconfig/ChangeLog | 980 ++
tlt3.0/tclconfig/README.txt | 26 +
tlt3.0/tclconfig/install-sh | 528 +
tlt3.0/tclconfig/tcl.m4 | 4150 ++++++++
unix/Makefile | 9 -
unix/rotstr.C | 4 +-
unix/rotstr.h | 2 +-
win/Makefile | 13 +-
350 files changed, 104501 insertions(+), 5214 deletions(-)
diff --git a/Makefile b/Makefile
index a34466a..42defcb 100644
--- a/Makefile
+++ b/Makefile
@@ -22,89 +22,12 @@ DIRS = bin lib include man share dist
DS9APP=SAOImage\ DS9\ $(DS9VERSION)
XPAAPP=XPA\ $(XPAVERSION)
-#--------------------------blt stuff
-
-BLTINCL = blt.h bltVector.h
-
-BLTWITHOUT = \
- --without-jpegincdir --without-jpeglibdir \
- --without-pngincdir --without-pnglibdir \
- --without-tiffincdir --without-tifflibdir \
- --without-xpmincdir --without-xpmlibdir \
- --without-xrandrincdir --without-xrandrlibdir \
- --without-expatincdir --without-expatlibdir \
- --without-mysqlincdir --without-mysqllibdir
-
-#--------------------------flags
-
-ifeq ($(OS),unix)
- PORT=unix
-
- TCLINSTALL=install
- TCLDIRDIR= $(TCLDIR)/unix
- TKDIRDIR= $(TKDIR)/unix
-
- XFLAGS = --x-includes=$(X11INCLUDE) --x-libraries=$(X11LIB)
-
- TCLFLAGS = $(XFLAGS) $(EXTTCLFLAGS) --prefix $(root) --enable-64bit --disable-shared --disable-threads
-
- TKTABLEFLAGS = $(XFLAGS) --prefix $(root) --disable-shared
- BLTFLAGS = $(XFLAGS) $(BLTWITHOUT)
- TKIMGFLAGS = $(XFLAGS)
- XPAFLAGS = $(XFLAGS)
-
- ZLIB=
- SIGNAL= signal
-endif
-
-ifeq ($(OS),windows)
- PORT= win
-
- TCLINSTALL=install
- TCLDIRDIR= $(TCLDIR)/win
- TKDIRDIR= $(TKDIR)/win
-
- TCLFLAGS = --prefix $(root) --disable-shared --disable-threads
-
- TKTABLEFLAGS = --prefix $(root) --disable-shared
- BLTFLAGS = --without-x $(BLTWITHOUT) \
- --without-xftincdir --without-xftlibdir
- TKIMGFLAGS =
- XPAFLAGS = --without-x
- PRETKHTMLFLAGS = config_BUILD_TCLSH=tclsh86sg \
- config_TARGET_TCL_SCRIPT_DIR=$(root)/lib/tcl8.6
-
- ZLIB=zlib
- SIGNAL=
-endif
-
-ifeq ($(OS),macosx)
- PORT= macosx
-
- TCLINSTALL=
- TCLDIRDIR= $(TCLDIR)/macosx
- TKDIRDIR= $(TKDIR)/macosx
-
- TKTABLEFLAGS = --prefix $(root)
-
- BLTFLAGS = $(BLTWITHOUT)
- TKIMGFLAGS =
-
-# xpa configure will not accept --without-x
- XPAFLAGS = --with-x=disabled --enable-posix_spawn
- PRETKHTMLFLAGS = config_TARGET_LIBS="-framework CoreFoundation -framework Carbon" \
- config_TARGET_X_INC="-I$(root)/$(TKDIR)/xlib" \
- config_TARGET_X_LIBS=" "
-
- FUNTOOLSFLAGS = --enable-posix_spawn
-
- ZLIB=
- SIGNAL= signal
-endif
+#--------------------------cvs stuff
CVSFILES = admin \
checkdns \
tkmpeg \
+ tlt3.0 \
COPYING \
copyright \
iis \
@@ -120,10 +43,13 @@ CVSFILES = admin \
make.darwinsnowleopard \
make.linux \
make.linux64 \
- make.macosxx86mountainlion \
+ make.macosxmountainlion \
make.source \
make.pkgs \
Makefile \
+ Makefile.unix \
+ Makefile.macosx \
+ Makefile.windows \
notes.txt \
mods \
README \
@@ -148,15 +74,7 @@ CVSFILES = admin \
#--------------------------build
-all: dirs \
- tcl tk \
- tktable tkcon xmlrpc blt \
- $(ZLIB) tclxml tkimg tkmpeg tkhtml \
- xpa iis checkdns $(SIGNAL) funtools \
- ast wcssubs \
- rice hcompress plio \
- $(PORT) \
- saotk zvfs ds9
+include Makefile.$(OS)
doc : FORCE
@echo "Making Documentation..."
@@ -180,22 +98,6 @@ dirs : FORCE
@echo "Installing Directories..."
@for d in $(DIRS); do if [ ! -d $$d ]; then mkdir $$d; fi done
-tcl : FORCE
- @echo "Installing Tcl..."
- cd $(TCLDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure $(TCLFLAGS)
- $(MAKE) -C $(TCLDIRDIR) -j $(JOBS) $(TCLINSTALL)
-
-tk : FORCE
- @echo "Installing Tk..."
- cd $(TKDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure $(TCLFLAGS)
- $(MAKE) -C $(TKDIRDIR) -j $(JOBS) $(TCLINSTALL)
-
-tktable : FORCE
- @echo "Installing TkTable..."
- cd $(TKTABLEDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure $(TKTABLEFLAGS)
- $(MAKE) -C $(TKTABLEDIR) -j $(JOBS)
- $(MAKE) -C $(TKTABLEDIR) -j $(JOBS) install
-
tkcon : FORCE
@echo "Installing TkCon..."
$(RM) -r lib/$(TKCONVER)
@@ -208,50 +110,34 @@ xmlrpc : FORCE
mkdir lib/$(XMLRPCVER)
cp $(XMLRPCDIR)/xmlrpc.tcl lib/$(XMLRPCVER)
-blt : FORCE
- @echo "Installing BLT..."
- cd $(BLTDIR); CC='$(CC)' CFLAGS='$(OPTS) -DUSE_INTERP_RESULT' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --with-tcl=$(root)/$(TCLDIRDIR) --with-tk=$(root)/$(TKDIRDIR) $(BLTFLAGS) --disable-shared
- cd $(BLTDIR)/src; $(MAKE) -j $(JOBS) build_static
- cp $(BLTDIR)/src/*.a lib/.
- cd $(BLTDIR)/src; cp $(BLTINCL) ../../include/.
-
zlib : FORCE
@echo "Installing zlib..."
- cd $(ZLIBDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --static
+ cd $(ZLIBDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --static
$(MAKE) -C $(ZLIBDIR) -j $(JOBS) install
-tclxml : FORCE
- @echo "Installing TCLXML..."
- cd $(TCLXMLDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --disable-shared --disable-threads --with-xml-static=1 $(TCLXMLFLAGS)
- $(MAKE) -C $(TCLXMLDIR) -j $(JOBS)
- $(MAKE) -C $(TCLXMLDIR) -j $(JOBS) install
-
-tkimg : libtiff
- @echo "Installing TKIMG..."
- cd $(TKIMGDIR); CC='$(CC)' CFLAGS='$(OPTS) -DPNG_NO_WRITE_gAMA' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --with-tcl=$(root)/$(TCLDIRDIR) --with-tk=$(root)/$(TKDIRDIR) $(TKIMGFLAGS) --disable-shared --disable-threads
- $(MAKE) -C $(TKIMGDIR) -j $(JOBS) install
-
libtiff : FORCE
@echo "Installing LIBTIFF..."
- cd $(TKIMGDIR)/compat/libtiff; CC='$(CC)' CFLAGS='$(OPTS)' CXX='$(CC)' CXXFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --disable-shared
+ cd $(TKIMGDIR)/compat/libtiff; CC='$(CC)' CFLAGS='$(OPTS)' CXX='$(CC)' \
+ CXXFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --disable-shared
$(MAKE) -C $(TKIMGDIR)/compat/libtiff -j $(JOBS) install
tkmpeg : FORCE
@echo "Installing TKMPEG..."
$(MAKE) -C $(TKMPEGDIR) -j $(JOBS) install
-tkhtml : $(HTMLDIR)
- @echo "Installing TKHTML..."
- cd $(HTMLDIR); CC='$(CC)' CFLAGS='$(OPTS) -DUSE_INTERP_RESULT' LDFLAGS='$(LIBS)' $(PRETKHTMLFLAGS) $(root)/htmlwidget/configure --prefix $(root) --with-tcl=$(root)/$(TCLDIR) --with-tk=$(root)/$(TKDIR) $(XFLAGS) --enable-shared=no
- $(MAKE) -C $(HTMLDIR) headers libtkhtml.a
- cp $(HTMLDIR)/libtkhtml.a lib/.
-
$(HTMLDIR) : FORCE
mkdir $(HTMLDIR)
xpa : FORCE
@echo "Installing XPA..."
- cd $(XPADIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --with-tcl=$(root)/$(TCLDIRDIR) $(XPAFLAGS) --disable-shared
+ cd $(XPADIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --prefix $(root) \
+ --disable-shared \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ $(XPAFLAGS)
$(MAKE) -C $(XPADIR) -j $(JOBS) install
cd bin; strip xpa*
@@ -269,19 +155,23 @@ signal: FORCE
funtools: FORCE
@echo "Installing Funtools..."
-# cd $(FUNTOOLSDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --with-zlib=../../lib/libz.a --with-wcslib=../lib/libwcs.a --enable-mainlib $(FUNTOOLSFLAGS)
- cd $(FUNTOOLSDIR); CC='$(CC)' CFLAGS='$(OPTS)' LDFLAGS='$(LIBS)' ./configure --prefix $(root) --with-wcslib=../lib/libwcs.a --enable-mainlib $(FUNTOOLSFLAGS)
+ cd $(FUNTOOLSDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --prefix $(root) \
+ --with-wcslib=../lib/libwcs.a \
+ --enable-mainlib $(FUNTOOLSFLAGS)
$(MAKE) -C $(FUNTOOLSDIR) lib
cp $(FUNTOOLSDIR)/libfuntools.a lib/.
ast : FORCE
@echo "Installing AST..."
- cd $(ASTDIR); \
- touch aclocal.m4; sleep 1; \
- touch Makefile.in; sleep 1; \
- touch configure; \
- ./configure --enable-shared=no --prefix=$(root) $(ASTFLAGS) CC='$(CC)' CFLAGS='$(OPTS) -I.'; \
- $(MAKE) -j $(JOBS) ast.h install-libLTLIBRARIES install-nodist_includeHEADERS install-includeHEADERS
+ cd $(ASTDIR); CC='$(CC)' CFLAGS='$(OPTS) -I.' \
+ ./configure \
+ --enable-shared=no \
+ --prefix=$(root) \
+ $(ASTFLAGS)
+ $(MAKE) -C $(ASTDIR) -j $(JOBS) ast.h install-libLTLIBRARIES \
+ install-nodist_includeHEADERS install-includeHEADERS
wcssubs : FORCE
@echo "Installing WCSSUBS..."
@@ -299,10 +189,6 @@ plio: FORCE
@echo "Installing PLIO..."
$(MAKE) -C $(PLIODIR) -j $(JOBS) install
-$(PORT) : FORCE
- @echo "Installing $(PORT)..."
- $(MAKE) -C $(PORT) -j $(JOBS) install
-
saotk : FORCE
@echo "Installing SAOTK..."
$(MAKE) -C $(SAOTKDIR) -j $(JOBS) install
@@ -327,16 +213,6 @@ ifeq ($(OS),windows)
find . -name "*stackdump*" -exec rm {} \;
endif
-distclean : tclclean tkclean \
- tktableclean bltclean \
- $(ZLIB)clean tclxmlclean tkimgclean tkmpegclean tkhtmlclean \
- xpaclean iisclean checkdnsclean $(SIGNAL)clean funtoolsclean \
- astclean wcssubsclean \
- riceclean hcompressclean plioclean \
- $(PORT)clean \
- saotkclean zvfsclean ds9clean srcclean \
- filesclean dirsclean
-
clean: FORCE
filesclean: FORCE
@@ -354,8 +230,8 @@ tkclean : FORCE
tktableclean: FORCE
$(MAKE) -C $(TKTABLEDIR) distclean
-bltclean: FORCE
- $(MAKE) -C $(BLTDIR) distclean
+tltclean: FORCE
+ $(MAKE) -C $(TLTDIR) distclean
zlibclean: FORCE
$(MAKE) -C $(ZLIBDIR) distclean
@@ -408,15 +284,6 @@ hcompressclean: FORCE
plioclean: FORCE
$(MAKE) -C $(PLIODIR) distclean
-unixclean : FORCE
- $(MAKE) -C unix distclean
-
-winclean : FORCE
- $(MAKE) -C win distclean
-
-macosxclean : FORCE
- $(MAKE) -C macosx distclean
-
saotkclean : FORCE
$(MAKE) -C $(SAOTKDIR) distclean
@@ -437,53 +304,12 @@ commit : FORCE
update : FORCE
cvs update $(CVSFILES)
-#--------------------------app
-
-ifeq ($(OS),windows)
-ds9app : ds9
- $(MAKE) -C $(DS9DIR) ds9app
-
-ds9winzip : FORCE
- $(RM) -f dist/$(DS9APP)\ Install.*
- /cygdrive/c/Program\ Files\ \(x86\)/WinZip/wzzip -p -r dist/$(DS9APP)\ Install.zip bin/ds9app
-# /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(DS9APP)\ Install.zip -setup -i ds9/win/ds9.ico -le -runasuser -t ds9/win/message.txt -a ds9/win/about.txt -c cscript install.vbs
- /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(DS9APP)\ Install.zip -d C:\\ds9 -i ds9/win/ds9.ico -le -overwrite -runasuser -c cscript install.vbs
-
-xpawinzip : FORCE
- $(RM) -f dist/$(XPAAPP)\ Install.*
- /cygdrive/c/Program\ Files\ \(x86\)/WinZip/wzzip dist/$(XPAAPP)\ Install.zip bin/xpa* bin/cygwin1.dll
- /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(XPAAPP)\ Install.zip -d C:\\ds9 -le -overwrite -runasuser
-endif
-
-ifeq ($(OS),macosx)
-ds9app : ds9
- $(MAKE) -C $(DS9DIR) ds9app
-
-ds9dmg : FORCE
- rm -rf dist/$(DS9APP)
- rm -rf dist/$(DS9APP).dmg
- mkdir dist/$(DS9APP)
- ln -s /Applications dist/$(DS9APP)/.
- cp -r ds9/macosx/README dist/$(DS9APP)/.
- cp -rp bin/SAOImage\ DS9.app dist/$(DS9APP)/.
- hdiutil create -srcfolder dist/$(DS9APP) dist/$(DS9APP)
-
-endif
-
#--------------------------distribution
dist : distds9 distxpa
distall : distds9 distxpa distdoc distsource
-ifeq ($(OS),windows)
-distapp : distds9app distxpaapp
-endif
-
-ifeq ($(OS),macosx)
-distapp : distds9app
-endif
-
ifdef CVS_SERVER
#--------------------------remote
@@ -494,29 +320,12 @@ distds9 : FORCE
scp dist/ds9.$(ARCH).$(DS9VERSION).tar.gz $(USER)@$(DEST):build/$(ARCH)/.
ssh $(USER)@$(DEST) 'cd build/$(ARCH); zcat ds9.$(ARCH).$(DS9VERSION).tar.gz | tar -xvf -'
-ifeq ($(OS),windows)
-distds9app : ds9winzip
- scp dist/$(DS9APP)\ Install.exe $(USER)@$(DEST):build/$(ARCH)/.
-endif
-
-ifeq ($(OS),macosx)
-distds9app : ds9dmg
- scp -r dist/$(DS9APP)/SAOImage\ DS9.app $(USER)@$(DEST):build/$(ARCH)/.
- scp dist/$(DS9APP).dmg $(USER)@$(DEST):build/$(ARCH)/.
-endif
-
distxpa : FORCE
@echo "Creating XPA Distribution"
cd bin; tar cvf - xpa*$(EXE) |gzip > ../dist/xpa.$(ARCH).$(XPAVERSION).tar.gz
scp dist/xpa.$(ARCH).$(XPAVERSION).tar.gz $(USER)@$(DEST):build/$(ARCH)/.
ssh $(USER)@$(DEST) 'cd build/$(ARCH); zcat xpa.$(ARCH).$(XPAVERSION).tar.gz | tar -xvf -'
-ifeq ($(OS),windows)
-distxpaapp : xpawinzip
- @echo "Creating XPA Distribution"
- scp dist/$(XPAAPP)\ Install.exe $(USER)@$(DEST):build/$(ARCH)/.
-endif
-
distdoc : doc
@echo "Creating Documentation Distribution"
scp -r doc $(USER)@$(DEST):build/.
@@ -541,26 +350,12 @@ distds9 : FORCE
cd bin; tar cvf - ds9$(EXE) $(ZIPFILE) | gzip > ../dist/ds9.$(ARCH).$(DS9VERSION).tar.gz
cp dist/ds9.$(ARCH).$(DS9VERSION).tar.gz $(HOME)/build/$(ARCH)/.
cd $(HOME)/build/$(ARCH); $(ZCAT) ds9.$(ARCH).$(DS9VERSION).tar.gz | tar -xvf -
-ifeq ($(OS),windows)
-distds9app : ds9winzip
- cp dist/ds9.$(ARCH).$(DS9VERSION).exe $(HOME)/build/$(ARCH)/.
-endif
-
-ifeq ($(OS),macosx)
-distds9app : ds9dmg
- cp -r dist/$(DS9APP)/SAOImage\ DS9.app $(HOME)/build/$(ARCH)/.
- cp dist/$(DS9APP).dmg $(HOME)/build/$(ARCH)/.
-endif
distxpa : FORCE
@echo "Creating XPA Distribution"
cd bin; tar cvf - xpa*$(EXE) |gzip > ../dist/xpa.$(ARCH).$(XPAVERSION).tar.gz
cp dist/xpa.$(ARCH).$(XPAVERSION).tar.gz $(HOME)/build/$(ARCH)/.
cd $(HOME)/build/$(ARCH); $(ZCAT) xpa.$(ARCH).$(XPAVERSION).tar.gz | tar -xvf -
-ifeq ($(OS),windows)
-distxpaapp : xpawinzip
- cp dist/xpa.$(ARCH).$(XPAVERSION).exe $(HOME)/build/$(ARCH)/.
-endif
distdoc : doc
@echo "Creating Documentation Distribution"
diff --git a/Makefile.macosx b/Makefile.macosx
new file mode 100644
index 0000000..26565b4
--- /dev/null
+++ b/Makefile.macosx
@@ -0,0 +1,172 @@
+TCLDIRDIR= $(TCLDIR)/macosx
+TKDIRDIR= $(TKDIR)/macosx
+
+XPAFLAGS = --with-x=disabled --enable-posix_spawn
+FUNTOOLSFLAGS = --enable-posix_spawn
+
+TCLFILES = \
+ $(TCLDIR)/generic/tcl.h \
+ $(TCLDIR)/generic/tclDecls.h \
+ $(TCLDIR)/generic/tclPlatDecls.h
+
+TKFILES = \
+ $(TKDIR)/generic/tk.h \
+ $(TKDIR)/generic/tkDecls.h \
+ $(TKDIR)/generic/tkPlatDecls.h \
+ $(TKDIR)/generic/tkIntXlibDecls.h \
+ $(TKDIR)/macosx/tkMacOSX.h
+
+all: dirs \
+ tcl tk \
+ tktable tkcon xmlrpc tlt \
+ tclxml tkimg tkmpeg tkhtml \
+ xpa iis checkdns signal funtools \
+ ast wcssubs \
+ rice hcompress plio \
+ macosx \
+ saotk ds9
+
+tcl : FORCE
+ @echo "Installing Tcl..."
+ cd $(TCLDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --enable-64bit \
+ --enable-symbols
+ $(MAKE) -C $(TCLDIRDIR) -j $(JOBS)
+
+ # install include, lib
+ cp -p $(TCLFILES) include/.
+ cp -p build/tcl/Tcl.framework/libtclstub8.6.a lib/.
+ cp -rp build/tcl/Tcl.framework/Versions/8.6/Resources/Scripts lib/tcl8.6
+ cp -rp build/tcl/Tcl.framework/Versions/8.6/Resources/tcl8 lib/.
+
+ # we need a working tclsh later
+ cp -p build/tcl/tclsh8.6 bin/.
+ install_name_tool -change /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl @executable_path/../build/tcl/Tcl.framework/Tcl bin/tclsh8.6
+
+tk : FORCE
+ @echo "Installing Tk..."
+ cd $(TKDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --enable-64bit \
+ --enable-symbols
+ $(MAKE) -C $(TKDIRDIR) -j $(JOBS)
+
+ # install include, lib
+ cp -rp $(TKDIR)/xlib/X11 include/.
+ cp -p $(TKFILES) include/.
+ cp -p build/tk/Tk.framework/libtkstub8.6.a lib/.
+ cp -rp build/tk/Tk.framework/Versions/8.6/Resources/Scripts lib/tk8.6
+
+tlt : FORCE
+ @echo "Installing TLT..."
+ cd $(TLTDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure $(XFLAGS) \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --with-tk=$(root)/$(TKDIRDIR) \
+ --prefix $(root) \
+ --exec-prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TLTDIR) -j $(JOBS) install
+
+tktable : FORCE
+ @echo "Installing TkTable..."
+ cd $(TKTABLEDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --with-tk=$(root)/$(TKDIRDIR) \
+ --with-tkinclude=$(root)/$(TKDIR)/generic \
+ --prefix $(root) \
+ --exec-prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS)
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS) install
+
+tclxml : FORCE
+ @echo "Installing TCLXML..."
+ cd $(TCLXMLDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --prefix $(root) \
+ --exec-prefix $(root) \
+ --disable-shared \
+ --with-xml-static=1
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS)
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS) install
+
+tkimg : libtiff
+ @echo "Installing TKIMG..."
+ cd $(TKIMGDIR); CC='$(CC)' CFLAGS='$(OPTS) -DPNG_NO_WRITE_gAMA' \
+ ./configure \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --with-tk=$(root)/$(TKDIRDIR) \
+ --prefix $(root) \
+ --exec-prefix $(root) \
+ --disable-shared
+ $(MAKE) -C $(TKIMGDIR) -j $(JOBS) install
+
+
+tkhtml : $(HTMLDIR)
+ @echo "Installing TKHTML..."
+ cd $(HTMLDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ config_TARGET_TCL_SCRIPT_DIR=$(root)/$(TCLDIRDIR) \
+ config_TARGET_TK_SCRIPT_DIR=$(root)/$(TKDIRDIR) \
+ config_TARGET_TCL_INC=$(root)/$(TCLDIR)/generic \
+ config_TARGET_TK_INC=$(root)/$(TKDIR)/generic \
+ config_TARGET_X_INC="-I$(root)/$(TKDIR)/xlib" \
+ config_TARGET_X_LIBS=" " \
+ $(root)/htmlwidget/configure \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --with-tk=$(root)/$(TKDIRDIR) \
+ --prefix $(root) \
+ --enable-shared=no
+ $(MAKE) -C $(HTMLDIR) headers libtkhtml.a
+ cp $(HTMLDIR)/libtkhtml.a lib/.
+
+macosx : FORCE
+ @echo "Installing macosx..."
+ $(MAKE) -C macosx -j $(JOBS) install
+
+distclean : tclclean tkclean \
+ tktableclean tltclean \
+ tclxmlclean tkimgclean tkmpegclean tkhtmlclean \
+ xpaclean iisclean checkdnsclean signalclean funtoolsclean \
+ astclean wcssubsclean \
+ riceclean hcompressclean plioclean \
+ macosxclean \
+ saotkclean zvfsclean ds9clean srcclean \
+ filesclean dirsclean
+
+macosxclean : FORCE
+ $(MAKE) -C macosx distclean
+
+ds9app : ds9
+ $(MAKE) -C $(DS9DIR) ds9app
+
+ds9dmg : FORCE
+ rm -rf dist/$(DS9APP)
+ rm -rf dist/$(DS9APP).dmg
+ mkdir dist/$(DS9APP)
+ ln -s /Applications dist/$(DS9APP)/.
+ cp -r ds9/macosx/README dist/$(DS9APP)/.
+ cp -rp bin/SAOImage\ DS9.app dist/$(DS9APP)/.
+ hdiutil create -srcfolder dist/$(DS9APP) dist/$(DS9APP)
+
+distapp : distds9app
+
+ifdef CVS_SERVER
+
+distds9app : ds9dmg
+ scp -r dist/$(DS9APP)/SAOImage\ DS9.app $(USER)@$(DEST):build/$(ARCH)/.
+ scp dist/$(DS9APP).dmg $(USER)@$(DEST):build/$(ARCH)/.
+
+else
+
+distds9app : ds9dmg
+ cp -r dist/$(DS9APP)/SAOImage\ DS9.app $(HOME)/build/$(ARCH)/.
+ cp dist/$(DS9APP).dmg $(HOME)/build/$(ARCH)/.
+
+endif
diff --git a/Makefile.unix b/Makefile.unix
new file mode 100644
index 0000000..39bbbf2
--- /dev/null
+++ b/Makefile.unix
@@ -0,0 +1,102 @@
+TCLDIRDIR= $(TCLDIR)/unix
+TKDIRDIR= $(TKDIR)/unix
+
+XFLAGS = --x-includes=$(X11INCLUDE) --x-libraries=$(X11LIB)
+XPAFLAGS = $(XFLAGS)
+FUNTOOLSFLAGS =
+
+all: dirs \
+ tcl tk \
+ tktable tkcon xmlrpc tlt \
+ tclxml tkimg tkmpeg tkhtml \
+ xpa iis checkdns signal funtools \
+ ast wcssubs \
+ rice hcompress plio \
+ unix \
+ saotk zvfs ds9
+
+tcl : FORCE
+ @echo "Installing Tcl..."
+ cd $(TCLDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure $(XFLAGS) $(TCLFLAGS) \
+ --prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TCLDIRDIR) -j $(JOBS) install
+
+tk : FORCE
+ @echo "Installing Tk..."
+ cd $(TKDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure $(XFLAGS) $(TCLFLAGS) \
+ --prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TKDIRDIR) -j $(JOBS) install
+
+tlt : FORCE
+ @echo "Installing TLT..."
+ cd $(TLTDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure $(XFLAGS) \
+ --prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TLTDIR) -j $(JOBS) install
+
+tktable : FORCE
+ @echo "Installing TkTable..."
+ cd $(TKTABLEDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure $(XFLAGS) \
+ --prefix $(root) \
+ --disable-shared \
+ --enable-symbols
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS)
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS) install
+
+tclxml : FORCE
+ @echo "Installing TCLXML..."
+ cd $(TCLXMLDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure \
+ --prefix $(root) \
+ --disable-shared
+ --with-xml-static=1
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS)
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS) install
+
+tkimg : libtiff
+ @echo "Installing TKIMG..."
+ cd $(TKIMGDIR); CC='$(CC)' CFLAGS='$(OPTS) -DPNG_NO_WRITE_gAMA' \
+ ./configure $(XFLAGS) \
+ --with-tcl=$(root)/$(TCLDIRDIR) \
+ --with-tk=$(root)/$(TKDIRDIR) \
+ --prefix $(root) \
+ --disable-shared
+ $(MAKE) -C $(TKIMGDIR) -j $(JOBS) install
+
+tkhtml : $(HTMLDIR)
+ @echo "Installing TKHTML..."
+ cd $(HTMLDIR); CC='$(CC)' CFLAGS='$(OPTS) -DUSE_INTERP_RESULT' \
+ $(root)/htmlwidget/configure $(XFLAGS) \
+ --with-tcl=$(root)/$(TCLDIR) \
+ --with-tk=$(root)/$(TKDIR) \
+ --prefix $(root) \
+ --enable-shared=no
+ $(MAKE) -C $(HTMLDIR) headers libtkhtml.a
+ cp $(HTMLDIR)/libtkhtml.a lib/.
+
+unix : FORCE
+ @echo "Installing unix..."
+ $(MAKE) -C unix -j $(JOBS) install
+
+distclean : tclclean tkclean \
+ tktableclean tltclean \
+ tclxmlclean tkimgclean tkmpegclean tkhtmlclean \
+ xpaclean iisclean checkdnsclean signalclean funtoolsclean \
+ astclean wcssubsclean \
+ riceclean hcompressclean plioclean \
+ unixclean \
+ saotkclean zvfsclean ds9clean srcclean \
+ filesclean dirsclean
+
+unixclean : FORCE
+ $(MAKE) -C unix distclean
+
diff --git a/Makefile.windows b/Makefile.windows
new file mode 100644
index 0000000..04321e6
--- /dev/null
+++ b/Makefile.windows
@@ -0,0 +1,116 @@
+TCLDIRDIR= $(TCLDIR)/win
+TKDIRDIR= $(TKDIR)/win
+
+XPAFLAGS = --without-x
+FUNTOOLSFLAGS =
+
+all: dirs \
+ tcl tk \
+ tktable tkcon xmlrpc tlt \
+ zlib tclxml tkimg tkmpeg tkhtml \
+ xpa iis checkdns funtools \
+ ast wcssubs \
+ rice hcompress plio \
+ win \
+ saotk zvfs ds9
+
+tcl : FORCE
+ @echo "Installing Tcl..."
+ cd $(TCLDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --disable-shared --disable-threads
+ $(MAKE) -C $(TCLDIRDIR) -j $(JOBS) install
+
+tk : FORCE
+ @echo "Installing Tk..."
+ cd $(TKDIRDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --disable-shared --disable-threads
+ $(MAKE) -C $(TKDIRDIR) -j $(JOBS) install
+
+tktable : FORCE
+ @echo "Installing TkTable..."
+ cd $(TKTABLEDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --disable-shared
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS)
+ $(MAKE) -C $(TKTABLEDIR) -j $(JOBS) install
+
+tlt : FORCE
+ @echo "Installing TLT..."
+ cd $(TLTDIR); CC='$(CC)' CFLAGS='$(OPTS) -DUSE_INTERP_RESULT' \
+ ./configure --prefix $(root) --with-tcl=$(root)/$(TCLDIRDIR) --with-tk=$(root)/$(TKDIRDIR) --without-x $(TLTWITHOUT) --without-xftincdir --without-xftlibdir --disable-shared
+ cd $(TLTDIR)/src; $(MAKE) -j $(JOBS) build_static
+ cp $(TLTDIR)/src/*.a lib/.
+ cd $(TLTDIR)/src; cp $(TLTINCL) ../../include/.
+
+tclxml : FORCE
+ @echo "Installing TCLXML..."
+ cd $(TCLXMLDIR); CC='$(CC)' CFLAGS='$(OPTS)' \
+ ./configure --prefix $(root) --disable-shared --disable-threads --with-xml-static=1 $(TCLXMLFLAGS)
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS)
+ $(MAKE) -C $(TCLXMLDIR) -j $(JOBS) install
+
+tkimg : libtiff
+ @echo "Installing TKIMG..."
+ cd $(TKIMGDIR); CC='$(CC)' CFLAGS='$(OPTS) -DPNG_NO_WRITE_gAMA' \
+ ./configure --prefix $(root) --with-tcl=$(root)/$(TCLDIRDIR) --with-tk=$(root)/$(TKDIRDIR) $(XFLAGS) --disable-shared --disable-threads
+ $(MAKE) -C $(TKIMGDIR) -j $(JOBS) install
+
+tkhtml : $(HTMLDIR)
+ @echo "Installing TKHTML..."
+ cd $(HTMLDIR); CC='$(CC)' CFLAGS='$(OPTS) -DUSE_INTERP_RESULT' \
+ config_BUILD_TCLSH=tclsh86sg config_TARGET_TCL_SCRIPT_DIR=$(root)/lib/tcl8.6 $(root)/htmlwidget/configure --prefix $(root) --with-tcl=$(root)/$(TCLDIR) --with-tk=$(root)/$(TKDIR) $(XFLAGS) --enable-shared=no
+ $(MAKE) -C $(HTMLDIR) headers libtkhtml.a
+ cp $(HTMLDIR)/libtkhtml.a lib/.
+
+win : FORCE
+ @echo "Installing win..."
+ $(MAKE) -C win -j $(JOBS) install
+
+distclean : tclclean tkclean \
+ tktableclean tltclean \
+ zlibclean tclxmlclean tkimgclean tkmpegclean tkhtmlclean \
+ xpaclean iisclean checkdnsclean funtoolsclean \
+ astclean wcssubsclean \
+ riceclean hcompressclean plioclean \
+ winclean \
+ saotkclean zvfsclean ds9clean srcclean \
+ filesclean dirsclean
+
+winclean : FORCE
+ $(MAKE) -C win distclean
+
+ds9app : ds9
+ $(MAKE) -C $(DS9DIR) ds9app
+
+ds9winzip : FORCE
+ $(RM) -f dist/$(DS9APP)\ Install.*
+ /cygdrive/c/Program\ Files\ \(x86\)/WinZip/wzzip -p -r dist/$(DS9APP)\ Install.zip bin/ds9app
+# /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(DS9APP)\ Install.zip -setup -i ds9/win/ds9.ico -le -runasuser -t ds9/win/message.txt -a ds9/win/about.txt -c cscript install.vbs
+ /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(DS9APP)\ Install.zip -d C:\\ds9 -i ds9/win/ds9.ico -le -overwrite -runasuser -c cscript install.vbs
+
+xpawinzip : FORCE
+ $(RM) -f dist/$(XPAAPP)\ Install.*
+ /cygdrive/c/Program\ Files\ \(x86\)/WinZip/wzzip dist/$(XPAAPP)\ Install.zip bin/xpa* bin/cygwin1.dll
+ /cygdrive/c/Program\ Files\ \(x86\)/WinZip\ Self-Extractor/WINZIPSE.EXE dist/$(XPAAPP)\ Install.zip -d C:\\ds9 -le -overwrite -runasuser
+
+distapp : distds9app distxpaapp
+
+ifdef CVS_SERVER
+
+distds9app : ds9winzip
+ scp dist/$(DS9APP)\ Install.exe $(USER)@$(DEST):build/$(ARCH)/.
+
+distxpaapp : xpawinzip
+ @echo "Creating XPA Distribution"
+ scp dist/$(XPAAPP)\ Install.exe $(USER)@$(DEST):build/$(ARCH)/.
+
+else
+
+distds9app : ds9winzip
+ cp dist/ds9.$(ARCH).$(DS9VERSION).exe $(HOME)/build/$(ARCH)/.
+
+distxpaapp : xpawinzip
+ cp dist/xpa.$(ARCH).$(XPAVERSION).exe $(HOME)/build/$(ARCH)/.
+
+endif
+
+FORCE :
diff --git a/blt3.0.1/configure b/blt3.0.1/configure
index 94d3687..d807195 100755
--- a/blt3.0.1/configure
+++ b/blt3.0.1/configure
@@ -12569,7 +12569,7 @@ else
fi
done
fi
-if test "x${TCL_LIB_DIR}" = "x" ; then
+if test "x${TCL_LIB_DIR}" = "xx" ; then
{ { echo "$as_me:$LINENO: error: Can't find tcl library ${libname} in \"${blt_with_tcl_lib_dir}\"" >&5
echo "$as_me: error: Can't find tcl library ${libname} in \"${blt_with_tcl_lib_dir}\"" >&2;}
{ (exit 1); exit 1; }; }
@@ -12606,7 +12606,7 @@ else
fi
done
fi
-if test "x${TK_LIB_DIR}" = "x" ; then
+if test "x${TK_LIB_DIR}" = "xx" ; then
{ { echo "$as_me:$LINENO: error: Can't find tk library." >&5
echo "$as_me: error: Can't find tk library." >&2;}
{ (exit 1); exit 1; }; }
diff --git a/blt3.0.1/src/bltUnixBitmap.c b/blt3.0.1/src/bltUnixBitmap.c
index 98ce0f8..9d74771 100644
--- a/blt3.0.1/src/bltUnixBitmap.c
+++ b/blt3.0.1/src/bltUnixBitmap.c
@@ -43,7 +43,9 @@
#include "bltPicture.h"
#endif
#include <X11/Xutil.h>
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
#include <X11/Xproto.h>
+#endif
#include "bltBitmap.h"
#define ROTATE_0 0
diff --git a/blt3.0.1/src/bltUnixPainter.c b/blt3.0.1/src/bltUnixPainter.c
index 73aa2fb..8012a36 100644
--- a/blt3.0.1/src/bltUnixPainter.c
+++ b/blt3.0.1/src/bltUnixPainter.c
@@ -43,7 +43,9 @@
#include "bltUnixPainter.h"
#include "bltPainter.h"
#include <X11/Xutil.h>
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
#include <X11/Xproto.h>
+#endif
typedef struct _Blt_Picture Pict;
@@ -941,10 +943,14 @@ DrawableToXImage(
int result;
result = TCL_OK;
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
errHandler = Tk_CreateErrorHandler(display, BadMatch, X_GetImage, -1,
- XGetImageErrorProc, &result);
+ XGetImageErrorProc, &result);
+#endif
imgPtr = XGetImage(display, drawable, x, y, w, h, AllPlanes, ZPixmap);
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
Tk_DeleteErrorHandler(errHandler);
+#endif
XSync(display, False);
if (result != TCL_OK) {
#ifdef notdef
diff --git a/blt3.0.1/src/bltUnixWindow.c b/blt3.0.1/src/bltUnixWindow.c
index bb07671..11f2d77 100644
--- a/blt3.0.1/src/bltUnixWindow.c
+++ b/blt3.0.1/src/bltUnixWindow.c
@@ -34,7 +34,7 @@
#include "bltInt.h"
#include <X11/Xlib.h>
-#ifndef WIN32
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
#include <X11/Xproto.h>
#endif
#include "tkDisplay.h"
@@ -277,8 +277,10 @@ Blt_GetWindowRegion(Display *display, Window window, int *xPtr, int *yPtr,
int x, y;
unsigned int w, h, bw, depth;
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
handler = Tk_CreateErrorHandler(display, any, X_GetGeometry, any,
XGeometryErrorProc, &result);
+#endif
result = XGetGeometry(display, window, &root, &x, &y, &w, &h, &bw, &depth);
if (!result) {
goto error;
@@ -326,7 +328,9 @@ Blt_GetWindowRegion(Display *display, Window window, int *xPtr, int *yPtr,
*yPtr = rootY;
}
}
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
Tk_DeleteErrorHandler(handler);
+#endif
XSync(display, False);
return TCL_OK;
error:
@@ -470,10 +474,14 @@ Blt_ReparentWindow(
int any = -1;
result = TCL_OK;
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
handler = Tk_CreateErrorHandler(display, any, X_ReparentWindow, any,
XReparentWindowErrorProc, &result);
+#endif
XReparentWindow(display, window, newParent, x, y);
+#if !defined(WIN32) && !defined(MAC_OSX_TCL)
Tk_DeleteErrorHandler(handler);
+#endif
XSync(display, False);
return result;
}
diff --git a/doc/release/r7.0.html b/doc/release/r7.0.html
index 825c37a..a20d2b6 100644
--- a/doc/release/r7.0.html
+++ b/doc/release/r7.0.html
@@ -493,6 +493,16 @@
<li><tt>06.26.2013 SEGMENT: add new segment region.</tt></li>
<li><tt>07.02.2013 ENVI: fixed a problem with calculating wcs.</tt></li>
<li><tt>07.02.2013 FITSY++: changes to allow 1D image.</tt></li>
+ <li><tt>07.03.2013 GROUPS: fixed a problem allowing multiple selection of region groups.</tt></li>
+ <li><tt>08.14.2013 WCS: Linear WCS now goes straight to AST.</tt></li> <li><tt>09.10.2013 PSEUDOCOLOR: rm support for pseudocolor visuals.</tt></li>
+ <li><tt>09.17.2013 REGIONS: PLOT3D dramatic improvements in speed of deep images and large regions.</tt></li>
+ <li><tt>09.17.2013 GUI: set last file directory based on file type last loaded.</tt></li>
+ <li><tt>09.18.2013 ENVI: minor change to hdr parser.</tt></li>
+ <li><tt>09.18.2013 ENVI: fixed a major problem with swapbytes.</tt></li>
+ <li><tt>09.18.2013 CATALOG: fixed a problem with selecting the correct region when arrow keys are used.</tt></li>
+ <li><tt>09.19.2013 FITSY++: cleaned up code for dumping array,nrrd,envi in native endian.</tt></li>
+ <li><tt>09.25.2013 AST: updated to version 7.3.2 to fix problem with SCAMP.</tt></li>
+ <li><tt>09.25.2013 FITSY++: fixed a problem parsing filters in the command line.</tt></li>
<li><tt><b>xx.xx.2013 RELEASE version 7.3</b></tt></li>
</ol>
</ol>
diff --git a/ds9/Makefile b/ds9/Makefile
index cb40601..0333e7d 100644
--- a/ds9/Makefile
+++ b/ds9/Makefile
@@ -1,324 +1,13 @@
include ../make.include
include ../make.pkgs
-#--------------------------defines
-
-ZDIR = zipdir/zvfsmntpt
-FFILES = $(ZDIR)/$(TCLVER) \
- $(ZDIR)/tcl8 \
- $(ZDIR)/$(TKVER) \
- $(ZDIR)/$(BLTVER) \
- $(ZDIR)/$(TCLLIBVER) \
- $(ZDIR)/$(TKCONVER) \
- $(ZDIR)/$(XMLRPCVER) \
- $(ZDIR)/src \
- $(ZDIR)/msgs \
- $(ZDIR)/doc \
- $(ZDIR)/cmaps \
- $(ZDIR)/template
-
-ifdef FILTERCOMPILER
-FILES = $(FFILES) \
- $(ZDIR)/$(FILTERCOMPILER)
-else
-FILES = $(FFILES)
-endif
-
-# for unix, macosx
-MAINDIR = ../$(TKDIR)/unix
-MAIN = tkAppInit
-
-LIBS = \
- ../lib/libsaotk.a \
- ../lib/libtkhtml.a \
- ../lib/libtkmpeg.a \
- ../lib/$(TCLXMLVER)/libTclxml3.2.a \
- ../lib/$(TKTABLEVER)/libTktable2.10.a \
- ../lib/$(TKIMGVER)/libtkimgpng1.4.a \
- ../lib/$(TKIMGVER)/libpngtcl1.4.3.a \
- ../lib/$(TKIMGVER)/libtkimgtiff1.4.a \
- ../lib/$(TKIMGVER)/libtifftcl3.9.4.a \
- ../lib/$(TKIMGVER)/libtkimgjpeg1.4.a \
- ../lib/$(TKIMGVER)/libjpegtcl8.2.a \
- ../lib/$(TKIMGVER)/libtkimggif1.4.a \
- ../lib/$(TKIMGVER)/libtkimgwindow1.4.a \
- ../lib/$(TKIMGVER)/libzlibtcl1.2.5.a \
- ../lib/$(TKIMGVER)/libtkimg1.4.a \
- ../lib/libtiff.a \
- ../lib/libfuntools.a \
- ../lib/librice.a \
- ../lib/libhcomp.a \
- ../lib/libplio.a \
- ../lib/libast.a \
- ../lib/libast_err.a \
- ../lib/libast_pal.a \
- ../lib/libsaotk.a \
- ../lib/libwcs.a \
- ../lib/libzvfs.a \
- ../lib/libxpa.a \
- ../lib/libiis.a \
- ../lib/libcheckdns.a \
- ../lib/libsignal_ext.a \
- ../lib/libxxlib.a \
- ../lib/libBLTX30.a \
- ../lib/libBLTCore30.a \
- ../lib/libtk8.6.a \
- ../lib/libtkstub8.6.a \
- ../lib/libtcl8.6.a \
- ../lib/libtclstub8.6.a \
-
-# if windows, redefine
-ifeq ($(OS),windows)
- MAINDIR = ../$(TKDIR)/win
- MAIN = winMain
- RES = ds9.res.o
-
- LIBS = \
- ../lib/libsaotk.a \
- ../lib/libtkhtml.a \
- ../lib/libtkmpeg.a \
- ../lib/$(TCLXMLVER)/Tclxml32.a \
- ../lib/$(TKTABLEVER)/Tktable210.a \
- ../lib/$(TKIMGVER)/tkimgpng14.a \
- ../lib/$(TKIMGVER)/pngtcl143.a \
- ../lib/$(TKIMGVER)/tkimgtiff14.a \
- ../lib/$(TKIMGVER)/tifftcl394.a \
- ../lib/$(TKIMGVER)/tkimgjpeg14.a \
- ../lib/$(TKIMGVER)/jpegtcl82.a \
- ../lib/$(TKIMGVER)/tkimggif14.a \
- ../lib/$(TKIMGVER)/tkimgwindow14.a \
- ../lib/$(TKIMGVER)/zlibtcl125.a \
- ../lib/$(TKIMGVER)/tkimg14.a \
- ../lib/libtiff.a \
- ../lib/libfuntools.a \
- ../lib/librice.a \
- ../lib/libhcomp.a \
- ../lib/libplio.a \
- ../lib/libast.a \
- ../lib/libast_err.a \
- ../lib/libast_pal.a \
- ../lib/libsaotk.a \
- ../lib/libwcs.a \
- ../lib/libzvfs.a \
- ../lib/libz.a \
- ../lib/libxpa.a \
- ../lib/libiis.a \
- ../lib/libcheckdns.a \
- ../lib/libxxlib.a \
- ../lib/libBLTX30.a \
- ../lib/libBLTCore30.a \
- ../lib/libtk86sg.a \
- ../lib/libtkstub86sg.a \
- ../lib/libtcl86sg.a \
- ../lib/libtclstub86sg.a
-endif
-
-OBJS = ds9.o $(MAIN).o $(RES)
-
-#--------------------------linux
-
-ifneq (,$(findstring linux,$(ARCH)))
-
-CFLAGS= $(CCOPT) -I. -I../include -I../$(TKDIR)/generic \
- -I../$(TKDIR)/unix -I$(X11INCLUDE)
-CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
-
-all: ds9
-
-ds9 : ds9Base ds9.zip
- $(RM) $@
- strip ds9Base
- cat ds9Base ds9.zip > ds9
- zip -A ds9
- chmod 755 ds9
- cp ds9 ../bin/.
-
-debug : ds9Base ds9.zip
- $(RM) $@
- cat ds9Base ds9.zip > ds9
- zip -A ds9
- chmod 755 ds9
-
-ds9Base : $(OBJS) $(LIBS)
- $(RM) $@
- $(CXX) ${OPTS} \
- -o $@ $(OBJS) $(LIBS) \
- -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss \
- -lxml2 \
- -lz -lpthread
-
-endif
-
-#--------------------------darwin
-
-ifneq (,$(findstring darwin,$(ARCH)))
-
-CFLAGS= $(CCOPT) -I. -I../include -I../$(TKDIR)/generic \
- -I../$(TKDIR)/unix -I$(X11INCLUDE)
-CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE) -DZIPFILE
-
-all: ds9
-
-ds9 : ds9Base ds9.zip
- $(RM) $@
- strip ds9Base
- cp ds9Base ds9
- cp ds9 ../bin/.
- cp ds9.zip ../bin/.
- cd ../bin; $(CODESIGN) -s "SAOImage DS9" ds9
-
-debug : ds9Base ds9.zip
- $(RM) $@
- cp ds9Base ds9
-
-ds9Base : $(OBJS) $(LIBS)
- $(RM) $@
- $(CXX) ${OPTS} \
- -o $@ $(OBJS) $(LIBS) \
- -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss -lfontconfig -lfreetype \
- -lxml2
-
-endif
-
-#--------------------------cygwin
-
-ifneq (,$(findstring cygwin,$(ARCH)))
-
-CFLAGS= $(CCOPT) -I. -I../include -I../$(TKDIR)/generic \
- -I../$(TKDIR)/unix -I$(X11INCLUDE)
-CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
-
-all: ds9
-
-ds9 : ds9Base ds9.zip
- $(RM) $@
- strip ds9Base
- cat ds9Base ds9.zip > ds9
- zip -A ds9
- chmod 755 ds9
- cp ds9 ../bin/.
-
-debug : ds9Base ds9.zip
- $(RM) $@
- cat ds9Base ds9.zip > ds9
- zip -A ds9
- chmod 755 ds9
-
-ds9Base : $(OBJS) $(LIBS)
- $(RM) $@
- $(CXX) ${OPTS} \
- -o $@ $(OBJS) $(LIBS) \
- -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss -lfontconfig -lfreetype \
- -ljbig \
- -lxml2
-
-endif
-
-#--------------------------windows
-
-ifeq ($(OS),windows)
-
-CFLAGS= $(CCOPT) -I. -I../include -I../$(TKDIR)/generic \
- -I../$(TKDIR)/win -I$(X11INCLUDE)
-CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE) -DZIPFILE
-
-all: ds9.exe
-
-ds9.exe : ds9Base.exe ds9.zip ../bin/tcc
- $(RM) $@
- strip ds9Base.exe
- cp ds9Base.exe ds9.exe
- cp ds9.exe ../bin/.
- cp ds9.zip ../bin/.
- cp /bin/cygwin1.dll ../bin/.
- cp /bin/cygxml2-2.dll ../bin/.
- cp /bin/cygstdc++-6.dll ../bin/.
- cp /bin/cygiconv-2.dll ../bin/.
- cp /bin/cygz.dll ../bin/.
- cp /bin/cyggcc_s-1.dll ../bin/.
- cp /bin/cygjbig-2.dll ../bin/.
- cp /bin/cyglzma-5.dll ../bin/.
-
-debug : ds9Base.exe ds9.zip ../bin/tcc
- $(RM) $@
- cp ds9Base.exe ds9.exe
-
-ds9app : ds9.exe
- $(RM) -r ../bin/ds9app
- mkdir ../bin/ds9app
- cp ds9.exe ../bin/ds9app/.
- cp ds9.zip ../bin/ds9app/.
- cp /bin/cygwin1.dll ../bin/ds9app/.
- cp /bin/cygxml2-2.dll ../bin/ds9app/.
- cp /bin/cygstdc++-6.dll ../bin/ds9app/.
- cp /bin/cygiconv-2.dll ../bin/ds9app/.
- cp /bin/cygz.dll ../bin/ds9app/.
- cp /bin/cyggcc_s-1.dll ../bin/ds9app/.
- cp /bin/cygjbig-2.dll ../bin/ds9app/.
- cp /bin/cyglzma-5.dll ../bin/ds9app/.
- cp -rp ../bin/tcc ../bin/ds9app/.
- cp ../ds9/win/install.vbs ../bin/ds9app/.
-
-ds9Base.exe: $(OBJS) $(LIBS)
- $(RM) $@
- $(CXX) ${OPTS} \
- -o $@ $(OBJS) $(LIBS) \
- -lxml2 -ljbig \
- -lws2_32 -limm32 -lcomctl32 -mwindows
-
-$(RES) : win/ds9.rc win/ds9.ico
- windres -o $@ --define STATIC_BUILD --include ../$(TKDIR)/generic \
- --include ../$(TCLDIR)/generic --include ../$(TKDIR)/win/rc \
- --include win win/ds9.rc
-
-../bin/tcc: ../compilers/$(TCC)
- $(RM) -r $@
- cd ../bin; unzip ../compilers/$(TCC)
- chmod +x ../bin/tcc/tcc.exe
- touch $@
-endif
-
-#--------------------------macosx
-
-ifeq ($(OS),macosx)
-
-CFLAGS= $(CCOPT) -I. -I../include -I../$(TKDIR)/generic \
- -I../$(TKDIR)/macosx -I$(X11INCLUDE)
-CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE) -DZIPFILE
-
-all: ds9
-
-ds9 : ds9Base ds9.zip
- $(RM) $@
- strip ds9Base
- cp ds9Base ds9
- cp ds9 ../bin/.
- cp ds9.zip ../bin/.
-
-debug : ds9Base ds9.zip
- $(RM) $@
- cp ds9Base ds9
-
-ds9app : ds9
- rm -rf ../bin/SAOImage\ DS9.app
- cp -rp macosx/SAOImage\ DS9.app ../bin/.
- cd ../bin/SAOImage\ DS9.app; find -d . -name CVS -exec rm -rf {} \;
- cp -p ../bin/ds9 ../bin/SAOImage\ DS9.app/Contents/MacOS/.
- cp -p ../bin/ds9.zip ../bin/SAOImage\ DS9.app/Contents/MacOS/.
- cd ../bin; $(CODESIGN) -s "SAOImage DS9" SAOImage\ DS9.app
-
-ds9Base : $(OBJS) $(LIBS)
- $(RM) $@
- $(CXX) ${OPTS} \
- -o $@ $(OBJS) $(LIBS) \
- -lxml2 \
- -lstdc++ -liconv \
- -sectcreate __TEXT __tk_rsrc ../$(TKDIR)/unix/tk8.6.rsrc \
- -framework CoreFoundation -framework Carbon
-endif
+include Makefile.$(OS)
#--------------------------support
+ds9.C : ds9.$(OS)
+ cp ds9.$(OS) ds9.C
+
$(MAIN).o : $(MAIN).c
$(CC) $(CFLAGS) -DTK_LOCAL_APPINIT=SAOAppInit \
-DTK_LOCAL_MAIN_HOOK=SAOLocalMainHook -c $(MAIN).c -o $@
@@ -326,94 +15,9 @@ $(MAIN).o : $(MAIN).c
$(MAIN).c : $(MAINDIR)/$(MAIN).c
cp $(MAINDIR)/$(MAIN).c .
-ds9.zip : $(FILES)
- cd zipdir; zip -r ../ds9.zip *
-
-zipdir :
- mkdir zipdir
- mkdir $(ZDIR)
-
-$(ZDIR)/$(TCLVER) : zipdir ../lib/$(TCLVER)
- $(RM) -r $@
- cp -r ../lib/$(TCLVER) $(ZDIR)/.
-
-$(ZDIR)/tcl8 : zipdir ../lib/tcl8
- $(RM) -r $@
- cp -r ../lib/tcl8 $(ZDIR)/.
-
-$(ZDIR)/$(TKVER) : zipdir ../lib/$(TKVER)
- $(RM) -r $@
- cp -r ../lib/$(TKVER) $(ZDIR)/.
- rm -rf $(ZDIR)/$(TKVER)/images
- rm -rf $(ZDIR)/$(TKVER)/demos
-
-$(ZDIR)/$(BLTVER) : zipdir
- $(RM) -r $@
- mkdir $(ZDIR)/$(BLTVER)
- mkdir $(ZDIR)/$(BLTVER)/afm
- cp ../$(BLTDIR)/library/graph.tcl $(ZDIR)/$(BLTVER)/.
- cp ../$(BLTDIR)/library/bltGraph.pro $(ZDIR)/$(BLTVER)/.
- cp ../$(BLTDIR)/library/tclIndex $(ZDIR)/$(BLTVER)/.
- cp ../$(BLTDIR)/library/afm/*.afm $(ZDIR)/$(BLTVER)/afm/.
-
-$(ZDIR)/$(TCLLIBVER) : zipdir
- $(RM) -r $@
- mkdir $(ZDIR)/$(TCLLIBVER)
- cp -r ../$(TCLLIBDIR)/modules/base64 $(ZDIR)/$(TCLLIBVER)/.
- cp -r ../$(TCLLIBDIR)/modules/ftp $(ZDIR)/$(TCLLIBVER)/.
- cp -r ../$(TCLLIBDIR)/modules/log $(ZDIR)/$(TCLLIBVER)/.
- cp -r ../$(TCLLIBDIR)/modules/textutil $(ZDIR)/$(TCLLIBVER)/.
- cp -r ../$(TCLLIBDIR)/modules/math $(ZDIR)/$(TCLLIBVER)/.
-
-$(ZDIR)/$(TKCONVER) : zipdir ../lib/$(TKCONVER)
- $(RM) -r $@
- cp -r ../lib/$(TKCONVER) $@
-
-$(ZDIR)/$(XMLRPCVER) : zipdir ../lib/$(XMLRPCVER)
- $(RM) -r $@
- cp -r ../lib/$(XMLRPCVER) $@
-
-$(ZDIR)/src : zipdir ../src/*.tcl
- $(RM) -r $@
- cp -r ../src $(ZDIR)/.
-
-$(ZDIR)/msgs : zipdir ../msgs/*
- $(RM) -r $@
- cp -r ../msgs $(ZDIR)/.
-
-$(ZDIR)/doc : zipdir ../doc/* ../doc/ref/* ../doc/user/* ../doc/release/*
- $(RM) -r $@
- cd ..; find doc -name "*.html" | cpio -pdmuv ds9/$(ZDIR)
- cd ..; find doc -name "*.gif" | cpio -pdmuv ds9/$(ZDIR)
- cd ..; find doc -name "*.png" | cpio -pdmuv ds9/$(ZDIR)
-
-$(ZDIR)/cmaps : zipdir ../cmaps/*
- $(RM) -r $@
- cp -r ../cmaps $(ZDIR)/.
-
-$(ZDIR)/template : zipdir ../template/*
- $(RM) -r $@
- cd ..; find template -name "*.tpl" | cpio -pdmuv ds9/$(ZDIR)
-
-ifdef FILTERCOMPILER
-$(ZDIR)/$(FILTERCOMPILER) : zipdir ../compilers/$(FILTERCOMPILER)
- $(RM) -r $@
- cp ../compilers/$(FILTERCOMPILER) $(ZDIR)/$(FILTERCOMPILER)
-endif
-
#--------------------------cleanup
clean : FORCE
$(RM) core *~ *#
-ifeq ($(OS),windows)
-distclean: FORCE
- $(RM) core *~ *# ds9Base.exe ds9.exe *.zip *.o
- $(RM) -r zipdir bin/tcc
-else
-distclean: FORCE
- $(RM) core *~ *# ds9Base ds9 *.zip *.o
- $(RM) -r zipdir
-endif
-
FORCE :
diff --git a/ds9/Makefile.macosx b/ds9/Makefile.macosx
new file mode 100644
index 0000000..9ff0957
--- /dev/null
+++ b/ds9/Makefile.macosx
@@ -0,0 +1,166 @@
+#--------------------------defines
+
+CFLAGS= $(CCOPT) -I. -I../include -I$(X11INCLUDE)
+CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
+
+MAINDIR = ../$(TKDIR)/unix
+MAIN = tkAppInit
+
+OBJS = ds9.o $(MAIN).o
+
+LIBS = \
+ ../lib/libsaotk.a \
+ ../lib/libtkhtml.a \
+ ../lib/libtkmpeg.a \
+ ../lib/$(TCLXMLVER)/libTclxml3.2.a \
+ ../lib/$(TKTABLEVER)/libTktable2.10.a \
+ ../lib/$(TKIMGVER)/libtkimgpng1.4.a \
+ ../lib/$(TKIMGVER)/libpngtcl1.4.3.a \
+ ../lib/$(TKIMGVER)/libtkimgtiff1.4.a \
+ ../lib/$(TKIMGVER)/libtifftcl3.9.4.a \
+ ../lib/$(TKIMGVER)/libtkimgjpeg1.4.a \
+ ../lib/$(TKIMGVER)/libjpegtcl8.2.a \
+ ../lib/$(TKIMGVER)/libtkimggif1.4.a \
+ ../lib/$(TKIMGVER)/libtkimgwindow1.4.a \
+ ../lib/$(TKIMGVER)/libzlibtcl1.2.5.a \
+ ../lib/$(TKIMGVER)/libtkimg1.4.a \
+ ../lib/libtiff.a \
+ ../lib/libfuntools.a \
+ ../lib/librice.a \
+ ../lib/libhcomp.a \
+ ../lib/libplio.a \
+ ../lib/libast.a \
+ ../lib/libast_err.a \
+ ../lib/libast_pal.a \
+ ../lib/libwcs.a \
+ ../lib/libxpa.a \
+ ../lib/libiis.a \
+ ../lib/libcheckdns.a \
+ ../lib/libsignal_ext.a \
+ ../lib/$(TLTVER)/libtlt3.0.a \
+ ../lib/libxxlib.a \
+ ../lib/libtkstub8.6.a \
+ ../lib/libtclstub8.6.a
+
+APPDIR = ../bin/SAOImage\ DS9.app
+DS9FW = ../bin/SAOImage\ DS9.app/Contents/Frameworks/ds9.framework
+DS9RES = ../bin/SAOImage\ DS9.app/Contents/Frameworks/ds9.framework/Resources
+TCLFW = ../bin/SAOImage\ DS9.app/Contents/Frameworks/Tcl.framework
+TCLRES = ../bin/SAOImage\ DS9.app/Contents/Frameworks/Tcl.framework/Resources
+TKFW = ../bin/SAOImage\ DS9.app/Contents/Frameworks/Tk.framework
+TKRES = ../bin/SAOImage\ DS9.app/Contents/Frameworks/Tk.framework/Resources
+
+#--------------------------main
+
+all: ds9app
+
+ds9app : ds9 app framework tcl tk tcllib tkcon xmlrpc tlt compiler
+ cp -p ds9 $(APPDIR)/Contents/MacOS/.
+ strip $(APPDIR)/Contents/MacOS/ds9
+ install_name_tool -change \
+ /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl \
+ @executable_path/../Frameworks/Tcl.framework/Tcl \
+ $(APPDIR)/Contents/MacOS/ds9
+ install_name_tool -change \
+ /Library/Frameworks/Tk.framework/Versions/8.6/Tk \
+ @executable_path/../Frameworks/Tk.framework/Tk \
+ $(APPDIR)/Contents/MacOS/ds9
+ cd ../bin; $(CODESIGN) -s "SAOImage DS9" SAOImage\ DS9.app
+
+debug : ds9 app framework tcl_debug tk_debug tcllib tkcon xmlrpc tlt compiler
+ cp -p ds9 $(APPDIR)/Contents/MacOS/.
+ install_name_tool -change \
+ /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl \
+ @executable_path/../Frameworks/Tcl.framework/Tcl \
+ $(APPDIR)/Contents/MacOS/ds9
+ install_name_tool -change \
+ /Library/Frameworks/Tk.framework/Versions/8.6/Tk \
+ @executable_path/../Frameworks/Tk.framework/Tk \
+ $(APPDIR)/Contents/MacOS/ds9
+ cd ../bin; $(CODESIGN) -s "SAOImage DS9" SAOImage\ DS9.app
+
+ds9 : $(OBJS) $(LIBS)
+ $(RM) $@
+ $(CXX) ${OPTS} \
+ -o $@ $(OBJS) $(LIBS) \
+ -lxml2 \
+ -lstdc++ -liconv \
+ -F/Users/joye/saods9/build/tcl -framework Tcl \
+ -F/Users/joye/saods9/build/tk -framework Tk \
+ -framework CoreFoundation -framework Cocoa \
+ -framework Carbon -framework IOKit
+
+app : FORCE
+ rm -rf $(APPDIR)
+ cp -rp macosx/SAOImage\ DS9.app ../bin/.
+
+framework: FORCE
+ mkdir $(DS9FW)
+ mkdir $(DS9RES)
+ cp -pr ../src $(DS9RES)/.
+ cp -pr ../msgs $(DS9RES)/.
+ cp -pr ../doc $(DS9RES)/.
+ cp -pr ../cmaps $(DS9RES)/.
+ cp -pr ../template $(DS9RES)/.
+ cp -pr ../template $(DS9RES)/.
+
+ rm $(DS9RES)/src/source.tcl
+ cd $(APPDIR); find -d . -name CVS -exec rm -rf {} \;
+ echo "pkg_mkIndex $(DS9RES)/src *.tcl; exit" | tclsh8.6
+
+tcl : FORCE
+ cp -p ../build/tcl/Tcl.framework/Versions/8.6/Tcl $(TCLFW)/.
+ cp -pr ../build/tcl/Tcl.framework/Versions/8.6/Resources/* $(TCLRES)/.
+
+tcl_debug: FORCE
+ cp -p ../build/tcl/Tcl.framework/Versions/8.6/Tcl_debug $(TCLFW)/Tcl
+ cp -pr ../build/tcl/Tcl.framework/Versions/8.6/Resources/* $(TCLRES)/.
+
+tk : FORCE
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Tk $(TKFW)/.
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Resources/Info.plist \
+ $(TKRES)/.
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Resources/license.terms \
+ $(TKRES)/.
+ cp -rp ../build/tk/Tk.framework/Versions/8.6/Resources/Scripts \
+ $(TKRES)/.
+tk_debug: FORCE
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Tk_debug $(TKFW)/Tk
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Resources/Info.plist \
+ $(TKRES)/.
+ cp -p ../build/tk/Tk.framework/Versions/8.6/Resources/license.terms \
+ $(TKRES)/.
+ cp -rp ../build/tk/Tk.framework/Versions/8.6/Resources/Scripts \
+ $(TKRES)/.
+
+tcllib : FORCE
+ mkdir $(DS9RES)/$(TCLLIBVER)
+ cp -pr ../$(TCLLIBDIR)/modules/base64 $(DS9RES)/$(TCLLIBVER)/.
+ cp -pr ../$(TCLLIBDIR)/modules/ftp $(DS9RES)/$(TCLLIBVER)/.
+ cp -pr ../$(TCLLIBDIR)/modules/log $(DS9RES)/$(TCLLIBVER)/.
+ cp -pr ../$(TCLLIBDIR)/modules/textutil $(DS9RES)/$(TCLLIBVER)/.
+ cp -pr ../$(TCLLIBDIR)/modules/math $(DS9RES)/$(TCLLIBVER)/.
+
+tkcon : FORCE
+ mkdir $(DS9RES)/$(TKCONVER)
+ cp -p ../$(TKCONDIR)/*.tcl $(DS9RES)/$(TKCONVER)/.
+
+xmlrpc : FORCE
+ mkdir $(DS9RES)/$(XMLRPCVER)
+ cp -p ../$(XMLRPCDIR)/xmlrpc.tcl $(DS9RES)/$(XMLRPCVER)/.
+ echo "pkg_mkIndex $(DS9RES)/$(XMLRPCVER) *.tcl; exit" | tclsh8.6
+
+tlt : FORCE
+ mkdir $(DS9RES)/$(TLTVER)
+ cp -p ../$(TLTDIR)/library/graph.tcl $(DS9RES)/$(TLTVER)/.
+ echo "pkg_mkindex $(DS9RES)/tlt3.0 *.tcl; exit" | tclsh8.6
+
+compiler: FORCE
+ cp -p ../compilers/$(FILTERCOMPILER) $(DS9RES)/.
+
+#--------------------------cleanup
+
+distclean: FORCE
+ $(RM) core *~ *# ds9Base ds9 ds9.C *.o
+
+
diff --git a/ds9/Makefile.unix b/ds9/Makefile.unix
new file mode 100644
index 0000000..6f94ab8
--- /dev/null
+++ b/ds9/Makefile.unix
@@ -0,0 +1,226 @@
+#--------------------------defines
+
+CFLAGS= $(CCOPT) -I. -I../include -I$(X11INCLUDE)
+
+MAINDIR = ../$(TKDIR)/unix
+MAIN = tkAppInit
+
+ZDIR = zipdir/zvfsmntpt
+OBJS = ds9.o $(MAIN).o
+
+FILES = \
+ $(ZDIR)/$(TCLVER) \
+ $(ZDIR)/tcl8 \
+ $(ZDIR)/$(TKVER) \
+ $(ZDIR)/$(TLTVER) \
+ $(ZDIR)/$(TCLLIBVER) \
+ $(ZDIR)/$(TKCONVER) \
+ $(ZDIR)/$(XMLRPCVER) \
+ $(ZDIR)/src \
+ $(ZDIR)/msgs \
+ $(ZDIR)/doc \
+ $(ZDIR)/cmaps \
+ $(ZDIR)/template
+
+LIBS = \
+ ../lib/libsaotk.a \
+ ../lib/libtkhtml.a \
+ ../lib/libtkmpeg.a \
+ ../lib/$(TCLXMLVER)/libTclxml3.2.a \
+ ../lib/$(TKTABLEVER)/libTktable2.10.a \
+ ../lib/$(TKIMGVER)/libtkimgpng1.4.a \
+ ../lib/$(TKIMGVER)/libpngtcl1.4.3.a \
+ ../lib/$(TKIMGVER)/libtkimgtiff1.4.a \
+ ../lib/$(TKIMGVER)/libtifftcl3.9.4.a \
+ ../lib/$(TKIMGVER)/libtkimgjpeg1.4.a \
+ ../lib/$(TKIMGVER)/libjpegtcl8.2.a \
+ ../lib/$(TKIMGVER)/libtkimggif1.4.a \
+ ../lib/$(TKIMGVER)/libtkimgwindow1.4.a \
+ ../lib/$(TKIMGVER)/libzlibtcl1.2.5.a \
+ ../lib/$(TKIMGVER)/libtkimg1.4.a \
+ ../lib/libtiff.a \
+ ../lib/libfuntools.a \
+ ../lib/librice.a \
+ ../lib/libhcomp.a \
+ ../lib/libplio.a \
+ ../lib/libast.a \
+ ../lib/libast_err.a \
+ ../lib/libast_pal.a \
+ ../lib/libsaotk.a \
+ ../lib/libwcs.a \
+ ../lib/libzvfs.a \
+ ../lib/libxpa.a \
+ ../lib/libiis.a \
+ ../lib/libcheckdns.a \
+ ../lib/libsignal_ext.a \
+ ../lib/libxxlib.a \
+ ../lib/$(TLTVER)/libtlt3.0.a \
+ ../lib/libtk8.6.a \
+ ../lib/libtkstub8.6.a \
+ ../lib/libtcl8.6.a \
+ ../lib/libtclstub8.6.a
+
+#--------------------------main
+
+all: ds9
+
+#--------------------------linux
+
+ifneq (,$(findstring linux,$(ARCH)))
+
+CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
+
+ds9 : ds9Base ds9.zip
+ $(RM) $@
+ strip ds9Base
+ cat ds9Base ds9.zip > ds9
+ zip -A ds9
+ chmod 755 ds9
+ cp ds9 ../bin/.
+
+debug : ds9Base ds9.zip
+ $(RM) $@
+ cat ds9Base ds9.zip > ds9
+ zip -A ds9
+ chmod 755 ds9
+
+ds9Base : $(OBJS) $(LIBS)
+ $(RM) $@
+ $(CXX) ${OPTS} \
+ -o $@ $(OBJS) $(LIBS) \
+ -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss \
+ -lxml2 \
+ -lz -lpthread
+
+endif
+
+#--------------------------darwin
+
+ifneq (,$(findstring darwin,$(ARCH)))
+
+CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE) -DZIPFILE
+
+ds9 : ds9Base ds9.zip
+ $(RM) $@
+ strip ds9Base
+ cp ds9Base ds9
+ cp ds9 ../bin/.
+ cp ds9.zip ../bin/.
+ cd ../bin; $(CODESIGN) -s "SAOImage DS9" ds9
+
+debug : ds9Base ds9.zip
+ $(RM) $@
+ cp ds9Base ds9
+
+ds9Base : $(OBJS) $(LIBS)
+ $(RM) $@
+ $(CXX) ${OPTS} \
+ -o $@ $(OBJS) $(LIBS) \
+ -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss -lfontconfig -lfreetype \
+ -lxml2
+
+endif
+
+#--------------------------cygwin
+
+ifneq (,$(findstring cygwin,$(ARCH)))
+
+CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
+
+ds9 : ds9Base ds9.zip
+ $(RM) $@
+ strip ds9Base
+ cat ds9Base ds9.zip > ds9
+ zip -A ds9
+ chmod 755 ds9
+ cp ds9 ../bin/.
+
+debug : ds9Base ds9.zip
+ $(RM) $@
+ cat ds9Base ds9.zip > ds9
+ zip -A ds9
+ chmod 755 ds9
+
+ds9Base : $(OBJS) $(LIBS)
+ $(RM) $@
+ $(CXX) ${OPTS} \
+ -o $@ $(OBJS) $(LIBS) \
+ -L$(X11LIB) -lX11 -lXext -lXft -lXrender -lXss -lfontconfig -lfreetype \
+ -ljbig \
+ -lxml2
+
+endif
+
+ds9.zip : $(FILES)
+ cd zipdir; find . -depth -name "CVS" -exec rm -r {} \;
+ cd zipdir; zip -r ../ds9.zip *
+
+zipdir :
+ mkdir zipdir
+ mkdir $(ZDIR)
+
+$(ZDIR)/$(TCLVER) : zipdir ../lib/$(TCLVER)
+ $(RM) -r $@
+ cp -r ../lib/$(TCLVER) $(ZDIR)/.
+
+$(ZDIR)/tcl8 : zipdir ../lib/tcl8
+ $(RM) -r $@
+ cp -r ../lib/tcl8 $(ZDIR)/.
+
+$(ZDIR)/$(TKVER) : zipdir ../lib/$(TKVER)
+ $(RM) -r $@
+ cp -r ../lib/$(TKVER) $(ZDIR)/.
+ rm -rf $(ZDIR)/$(TKVER)/images
+ rm -rf $(ZDIR)/$(TKVER)/demos
+
+$(ZDIR)/$(TLTVER) : zipdir
+ $(RM) -r $@
+ mkdir $(ZDIR)/$(TLTVER)
+ cp ../$(TLTDIR)/library/graph.tcl $(ZDIR)/$(TLTVER)/.
+ cp ../$(TLTDIR)/library/bltGraph.pro $(ZDIR)/$(TLTVER)/.
+ cp -rp ../$(TLTDIR)/library/afm $(ZDIR)/$(TLTVER)/.
+
+$(ZDIR)/$(TCLLIBVER) : zipdir
+ $(RM) -r $@
+ mkdir $(ZDIR)/$(TCLLIBVER)
+ cp -r ../$(TCLLIBDIR)/modules/base64 $(ZDIR)/$(TCLLIBVER)/.
+ cp -r ../$(TCLLIBDIR)/modules/ftp $(ZDIR)/$(TCLLIBVER)/.
+ cp -r ../$(TCLLIBDIR)/modules/log $(ZDIR)/$(TCLLIBVER)/.
+ cp -r ../$(TCLLIBDIR)/modules/textutil $(ZDIR)/$(TCLLIBVER)/.
+ cp -r ../$(TCLLIBDIR)/modules/math $(ZDIR)/$(TCLLIBVER)/.
+
+$(ZDIR)/$(TKCONVER) : zipdir ../lib/$(TKCONVER)
+ $(RM) -r $@
+ cp -r ../lib/$(TKCONVER) $@
+
+$(ZDIR)/$(XMLRPCVER) : zipdir ../lib/$(XMLRPCVER)
+ $(RM) -r $@
+ cp -r ../lib/$(XMLRPCVER) $@
+
+$(ZDIR)/src : zipdir ../src/*.tcl
+ $(RM) -r $@
+ cp -r ../src $(ZDIR)/.
+
+$(ZDIR)/msgs : zipdir ../msgs/*
+ $(RM) -r $@
+ cp -r ../msgs $(ZDIR)/.
+
+$(ZDIR)/doc : zipdir ../doc/* ../doc/ref/* ../doc/user/* ../doc/release/*
+ $(RM) -r $@
+ cd ..; find doc -name "*.html" | cpio -pdmuv ds9/$(ZDIR)
+ cd ..; find doc -name "*.gif" | cpio -pdmuv ds9/$(ZDIR)
+ cd ..; find doc -name "*.png" | cpio -pdmuv ds9/$(ZDIR)
+
+$(ZDIR)/cmaps : zipdir ../cmaps/*
+ $(RM) -r $@
+ cp -r ../cmaps $(ZDIR)/.
+
+$(ZDIR)/template : zipdir ../template/*
+ $(RM) -r $@
+ cd ..; find template -name "*.tpl" | cpio -pdmuv ds9/$(ZDIR)
+
+#--------------------------cleanup
+
+distclean: FORCE
+ $(RM) core *~ *# ds9Base ds9 ds9.C *.zip *.o
+ $(RM) -r zipdir
diff --git a/ds9/Makefile.windows b/ds9/Makefile.windows
new file mode 100644
index 0000000..a62de04
--- /dev/null
+++ b/ds9/Makefile.windows
@@ -0,0 +1,132 @@
+#--------------------------defines
+
+CFLAGS= $(CCOPT) -I. -I../include -I$(X11INCLUDE)
+CXXFLAGS = $(CXXOPT) -I. -I../include -I$(X11INCLUDE)
+
+MAINDIR = ../$(TKDIR)/win
+MAIN = winMain
+RES = ds9.res.o
+
+OBJS = ds9.o $(MAIN).o $(RES)
+
+ZDIR = zipdir/zvfsmntpt
+FFILES = \
+ $(ZDIR)/$(TCLVER) \
+ $(ZDIR)/tcl8 \
+ $(ZDIR)/$(TKVER) \
+ $(ZDIR)/$(TLTVER) \
+ $(ZDIR)/$(TCLLIBVER) \
+ $(ZDIR)/$(TKCONVER) \
+ $(ZDIR)/$(XMLRPCVER) \
+ $(ZDIR)/src \
+ $(ZDIR)/msgs \
+ $(ZDIR)/doc \
+ $(ZDIR)/cmaps \
+ $(ZDIR)/template
+
+ifdef FILTERCOMPILER
+ FILES = $(FFILES) $(ZDIR)/$(FILTERCOMPILER)
+else
+ FILES = $(FFILES)
+endif
+
+LIBS = \
+ ../lib/libsaotk.a \
+ ../lib/libtkhtml.a \
+ ../lib/libtkmpeg.a \
+ ../lib/$(TCLXMLVER)/Tclxml32.a \
+ ../lib/$(TKTABLEVER)/Tktable210.a \
+ ../lib/$(TKIMGVER)/tkimgpng14.a \
+ ../lib/$(TKIMGVER)/pngtcl143.a \
+ ../lib/$(TKIMGVER)/tkimgtiff14.a \
+ ../lib/$(TKIMGVER)/tifftcl394.a \
+ ../lib/$(TKIMGVER)/tkimgjpeg14.a \
+ ../lib/$(TKIMGVER)/jpegtcl82.a \
+ ../lib/$(TKIMGVER)/tkimggif14.a \
+ ../lib/$(TKIMGVER)/tkimgwindow14.a \
+ ../lib/$(TKIMGVER)/zlibtcl125.a \
+ ../lib/$(TKIMGVER)/tkimg14.a \
+ ../lib/libtiff.a \
+ ../lib/libfuntools.a \
+ ../lib/librice.a \
+ ../lib/libhcomp.a \
+ ../lib/libplio.a \
+ ../lib/libast.a \
+ ../lib/libast_err.a \
+ ../lib/libast_pal.a \
+ ../lib/libwcs.a \
+ ../lib/libzvfs.a \
+ ../lib/libz.a \
+ ../lib/libxpa.a \
+ ../lib/libiis.a \
+ ../lib/libcheckdns.a \
+ ../lib/libxxlib.a \
+ ../lib/libBLTX30.a \
+ ../lib/libBLTCore30.a \
+ ../lib/libtk86sg.a \
+ ../lib/libtkstub86sg.a \
+ ../lib/libtcl86sg.a \
+ ../lib/libtclstub86sg.a
+
+#--------------------------main
+
+all: ds9.exe
+
+ds9.exe : ds9Base.exe ds9.zip ../bin/tcc
+ $(RM) $@
+ strip ds9Base.exe
+ cp ds9Base.exe ds9.exe
+ cp ds9.exe ../bin/.
+ cp ds9.zip ../bin/.
+ cp /bin/cygwin1.dll ../bin/.
+ cp /bin/cygxml2-2.dll ../bin/.
+ cp /bin/cygstdc++-6.dll ../bin/.
+ cp /bin/cygiconv-2.dll ../bin/.
+ cp /bin/cygz.dll ../bin/.
+ cp /bin/cyggcc_s-1.dll ../bin/.
+ cp /bin/cygjbig-2.dll ../bin/.
+ cp /bin/cyglzma-5.dll ../bin/.
+
+debug : ds9Base.exe ds9.zip ../bin/tcc
+ $(RM) $@
+ cp ds9Base.exe ds9.exe
+
+ds9app : ds9.exe
+ $(RM) -r ../bin/ds9app
+ mkdir ../bin/ds9app
+ cp ds9.exe ../bin/ds9app/.
+ cp ds9.zip ../bin/ds9app/.
+ cp /bin/cygwin1.dll ../bin/ds9app/.
+ cp /bin/cygxml2-2.dll ../bin/ds9app/.
+ cp /bin/cygstdc++-6.dll ../bin/ds9app/.
+ cp /bin/cygiconv-2.dll ../bin/ds9app/.
+ cp /bin/cygz.dll ../bin/ds9app/.
+ cp /bin/cyggcc_s-1.dll ../bin/ds9app/.
+ cp /bin/cygjbig-2.dll ../bin/ds9app/.
+ cp /bin/cyglzma-5.dll ../bin/ds9app/.
+ cp -rp ../bin/tcc ../bin/ds9app/.
+ cp ../ds9/win/install.vbs ../bin/ds9app/.
+
+ds9Base.exe: $(OBJS) $(LIBS)
+ $(RM) $@
+ $(CXX) ${OPTS} \
+ -o $@ $(OBJS) $(LIBS) \
+ -lxml2 -ljbig \
+ -lws2_32 -limm32 -lcomctl32 -mwindows
+
+$(RES) : win/ds9.rc win/ds9.ico
+ windres -o $@ --define STATIC_BUILD --include ../$(TKDIR)/generic \
+ --include ../$(TCLDIR)/generic --include ../$(TKDIR)/win/rc \
+ --include win win/ds9.rc
+
+../bin/tcc: ../compilers/$(TCC)
+ $(RM) -r $@
+ cd ../bin; unzip ../compilers/$(TCC)
+ chmod +x ../bin/tcc/tcc.exe
+ touch $@
+
+#--------------------------cleanup
+
+distclean: FORCE
+ $(RM) core *~ *# ds9Base.exe ds9.exe *.zip *.o
+ $(RM) -r zipdir bin/tcc
diff --git a/ds9/ds9.C b/ds9/ds9.macosx
similarity index 63%
copy from ds9/ds9.C
copy to ds9/ds9.macosx
index 9005192..19809db 100644
--- a/ds9/ds9.C
+++ b/ds9/ds9.macosx
@@ -11,6 +11,8 @@ using namespace std;
#include <tcl.h>
#include <tk.h>
+#define DEBUGS(x) {FILE* fp=fopen("/Users/joye/debug.txt","a+");fprintf(fp,"%s\n",x);fclose(fp);}
+
extern "C" {
int SAOAppInit(Tcl_Interp *interp);
int SAOLocalMainHook(int* argc, char*** argv);
@@ -20,8 +22,7 @@ extern "C" {
int Zvfs_Init(Tcl_Interp*);
int Zvfs_Mount(Tcl_Interp*, char*, char *);
- int Blt_core_Init(Tcl_Interp*);
- int Blt_x_Init(Tcl_Interp*);
+ int Tlt_Init(Tcl_Interp*);
int Tktable_Init(Tcl_Interp*);
int Checkdns_Init(Tcl_Interp*);
int Saotk_Init(Tcl_Interp*);
@@ -45,25 +46,11 @@ extern "C" {
int Tclxml_Init(Tcl_Interp*);
int Tclxml_libxml2_Init(Tcl_Interp*);
-#ifndef _GWIN32
int Signal_ext_Init(Tcl_Interp*);
-#endif
-#ifdef _MACOSX
int Tkmacosx_Init(Tcl_Interp*);
-#endif
-#ifdef _GWIN32
- int Tkwin32_Init(Tcl_Interp*);
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-
-#endif
}
-static char* appname = NULL;
-char* dupstr(const char* str);
Tcl_Interp *global_interp;
void internalError(const char* msg)
@@ -72,108 +59,55 @@ void internalError(const char* msg)
Tcl_SetVar2(global_interp, "ds9", "msg,level", "error", TCL_GLOBAL_ONLY);
}
-// currently use relative path
-// using full path with spaces causes problems
-// with htmwidget and tcl/tk
+extern char* dupstr(const char* str);
int SAOLocalMainHook(int* argcPtr, char*** argvPtr)
{
// sync C++ io calls with C io calls
ios::sync_with_stdio();
- // save real application name
- int argc = *argcPtr;
+ // do this first
+ Tcl_FindExecutable((*argvPtr)[0]);
+
+ // startup script
+ // use exec path, but remove name
+ int argc=*argcPtr;
char** argv = *argvPtr;
- appname = dupstr(argv[0]);
-
- // so that tcl and tk know where to find their libs
- // we do it here before InitLibraryPath is called
- putenv((char*)"TCL_LIBRARY=./zvfsmntpt/tcl8.6");
- putenv((char*)"TK_LIBRARY=./zvfsmntpt/tk8.6");
- // putenv((char*)"TCL_LIBRARY=/tmp/zvfsmntpt/tcl8.6");
- // putenv((char*)"TK_LIBRARY=/tmp/zvfsmntpt/tk8.6");
-
- // invoke startup script
- Tcl_Obj *path = Tcl_NewStringObj("./zvfsmntpt/src/ds9.tcl",-1);
- // Tcl_Obj *path = Tcl_NewStringObj("/tmp/zvfsmntpt/src/ds9.tcl",-1);
+ char* dir = dupstr(argv[0]);
+ char* ptr = dir+strlen(dir);
+ while (*ptr != '/' && ptr != dir)
+ ptr--;
+ *ptr = '\0';
+
+ ostringstream str;
+ str << dir
+ << "/../Frameworks/ds9.framework/Resources/src/ds9.tcl"
+ << ends;
+ char* ss = (char*)str.str().c_str();
+ delete [] dir;
+
+ Tcl_Obj *path = Tcl_NewStringObj(ss,-1);
Tcl_SetStartupScript(path, NULL);
}
int SAOAppInit(Tcl_Interp *interp)
{
- // reset argv0
- if (appname) {
- Tcl_SetVar(interp, "argv0", appname, TCL_GLOBAL_ONLY);
- delete [] appname;
- }
-
// save interp for cputs function
global_interp = interp;
- // We have to initialize the virtual filesystem before calling
- // Tcl_Init(). Otherwise, Tcl_Init() will not be able to find
- // its startup script files.
- if (Zvfs_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "zvfs", Zvfs_Init, (Tcl_PackageInitProc*)NULL);
-
- // find current working directory, and set as mount point
- {
- Tcl_DString pwd;
- Tcl_DStringInit(&pwd);
- Tcl_GetCwd(interp, &pwd);
-#ifdef ZIPFILE
- ostringstream str;
-#ifndef _GWIN32
- str << (char *)Tcl_GetNameOfExecutable()
- << ".zip"
- << ends;
-#else
- str << (char *)Tcl_GetNameOfExecutable()
- << "/../ds9.zip"
- << ends;
-#endif
- if( Zvfs_Mount(interp, (char*)str.str().c_str(), Tcl_DStringValue(&pwd)) != TCL_OK ){
- char str[] = "ERROR: Unable to open the auxiliary ds9 file 'ds9.zip'. If you moved the ds9 program from its original location, please also move the zip file to the same place.";
-
-#ifndef _GWIN32
- cerr << str << endl;
-#else
- MessageBox(NULL, str, "SAOImage DS9", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
-#endif
- exit(1);
- }
-#else
- Zvfs_Mount(interp, (char *)Tcl_GetNameOfExecutable(),
- Tcl_DStringValue(&pwd));
-#endif
- Tcl_DStringFree(&pwd);
- }
-
// Initialize Tcl and Tk
- if (Tcl_Init(interp))
+ if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
// Tk
- if (Tk_Init(interp))
+ if (Tk_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage(interp,"Tk", Tk_Init, Tk_SafeInit);
- {
- Tcl_DString pwd;
- Tcl_DStringInit(&pwd);
- Tcl_GetCwd(interp, &pwd);
- Tcl_DStringFree(&pwd);
- }
-
- // Blt
- if (Blt_core_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_core", Blt_core_Init,
- (Tcl_PackageInitProc*)NULL);
- if (Blt_x_Init(interp) == TCL_ERROR)
+ // tlt
+ if (Tlt_Init(interp) == TCL_ERROR)
return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_extra", Blt_x_Init,
+ Tcl_StaticPackage(interp, "tlt", Tlt_Init,
(Tcl_PackageInitProc*)NULL);
// Tktable
@@ -283,27 +217,16 @@ int SAOAppInit(Tcl_Interp *interp)
(Tcl_PackageInitProc*)NULL);
// Signal_Ext
-#ifndef _GWIN32
if (Signal_ext_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage (interp, "signal", Signal_ext_Init,
(Tcl_PackageInitProc*)NULL);
-#endif
-#ifdef _MACOSX
+ // Macosx
if (Tkmacosx_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage (interp, "macosx", Tkmacosx_Init,
(Tcl_PackageInitProc*)NULL);
-#endif
-
-#ifdef _GWIN32
- if (Tkwin32_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "win32", Tkwin32_Init,
- (Tcl_PackageInitProc*)NULL);
-#endif
return TCL_OK;
}
-
diff --git a/ds9/ds9.C b/ds9/ds9.unix
similarity index 77%
copy from ds9/ds9.C
copy to ds9/ds9.unix
index 9005192..96d38f1 100644
--- a/ds9/ds9.C
+++ b/ds9/ds9.unix
@@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in "copyright"
#include <stdlib.h>
+#include <string.h>
#include <iostream>
#include <sstream>
@@ -20,8 +21,7 @@ extern "C" {
int Zvfs_Init(Tcl_Interp*);
int Zvfs_Mount(Tcl_Interp*, char*, char *);
- int Blt_core_Init(Tcl_Interp*);
- int Blt_x_Init(Tcl_Interp*);
+ int Tlt_Init(Tcl_Interp*);
int Tktable_Init(Tcl_Interp*);
int Checkdns_Init(Tcl_Interp*);
int Saotk_Init(Tcl_Interp*);
@@ -45,25 +45,9 @@ extern "C" {
int Tclxml_Init(Tcl_Interp*);
int Tclxml_libxml2_Init(Tcl_Interp*);
-#ifndef _GWIN32
int Signal_ext_Init(Tcl_Interp*);
-#endif
-
-#ifdef _MACOSX
- int Tkmacosx_Init(Tcl_Interp*);
-#endif
-#ifdef _GWIN32
- int Tkwin32_Init(Tcl_Interp*);
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#undef WIN32_LEAN_AND_MEAN
-
-#endif
}
-static char* appname = NULL;
-char* dupstr(const char* str);
Tcl_Interp *global_interp;
void internalError(const char* msg)
@@ -81,32 +65,21 @@ int SAOLocalMainHook(int* argcPtr, char*** argvPtr)
// sync C++ io calls with C io calls
ios::sync_with_stdio();
- // save real application name
- int argc = *argcPtr;
- char** argv = *argvPtr;
- appname = dupstr(argv[0]);
+ // do this first
+ Tcl_FindExecutable((*argvPtr)[0]);
// so that tcl and tk know where to find their libs
// we do it here before InitLibraryPath is called
putenv((char*)"TCL_LIBRARY=./zvfsmntpt/tcl8.6");
putenv((char*)"TK_LIBRARY=./zvfsmntpt/tk8.6");
- // putenv((char*)"TCL_LIBRARY=/tmp/zvfsmntpt/tcl8.6");
- // putenv((char*)"TK_LIBRARY=/tmp/zvfsmntpt/tk8.6");
- // invoke startup script
+ // startup script
Tcl_Obj *path = Tcl_NewStringObj("./zvfsmntpt/src/ds9.tcl",-1);
- // Tcl_Obj *path = Tcl_NewStringObj("/tmp/zvfsmntpt/src/ds9.tcl",-1);
Tcl_SetStartupScript(path, NULL);
}
int SAOAppInit(Tcl_Interp *interp)
{
- // reset argv0
- if (appname) {
- Tcl_SetVar(interp, "argv0", appname, TCL_GLOBAL_ONLY);
- delete [] appname;
- }
-
// save interp for cputs function
global_interp = interp;
@@ -122,25 +95,16 @@ int SAOAppInit(Tcl_Interp *interp)
Tcl_DString pwd;
Tcl_DStringInit(&pwd);
Tcl_GetCwd(interp, &pwd);
+
#ifdef ZIPFILE
ostringstream str;
-#ifndef _GWIN32
str << (char *)Tcl_GetNameOfExecutable()
<< ".zip"
<< ends;
-#else
- str << (char *)Tcl_GetNameOfExecutable()
- << "/../ds9.zip"
- << ends;
-#endif
if( Zvfs_Mount(interp, (char*)str.str().c_str(), Tcl_DStringValue(&pwd)) != TCL_OK ){
char str[] = "ERROR: Unable to open the auxiliary ds9 file 'ds9.zip'. If you moved the ds9 program from its original location, please also move the zip file to the same place.";
-#ifndef _GWIN32
cerr << str << endl;
-#else
- MessageBox(NULL, str, "SAOImage DS9", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
-#endif
exit(1);
}
#else
@@ -151,29 +115,18 @@ int SAOAppInit(Tcl_Interp *interp)
}
// Initialize Tcl and Tk
- if (Tcl_Init(interp))
+ if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
// Tk
- if (Tk_Init(interp))
+ if (Tk_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage(interp,"Tk", Tk_Init, Tk_SafeInit);
- {
- Tcl_DString pwd;
- Tcl_DStringInit(&pwd);
- Tcl_GetCwd(interp, &pwd);
- Tcl_DStringFree(&pwd);
- }
-
- // Blt
- if (Blt_core_Init(interp) == TCL_ERROR)
+ // tlt
+ if (Tlt_Init(interp) == TCL_ERROR)
return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_core", Blt_core_Init,
- (Tcl_PackageInitProc*)NULL);
- if (Blt_x_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_extra", Blt_x_Init,
+ Tcl_StaticPackage(interp, "tlt", Tlt_Init,
(Tcl_PackageInitProc*)NULL);
// Tktable
@@ -283,27 +236,10 @@ int SAOAppInit(Tcl_Interp *interp)
(Tcl_PackageInitProc*)NULL);
// Signal_Ext
-#ifndef _GWIN32
if (Signal_ext_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage (interp, "signal", Signal_ext_Init,
(Tcl_PackageInitProc*)NULL);
-#endif
-
-#ifdef _MACOSX
- if (Tkmacosx_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "macosx", Tkmacosx_Init,
- (Tcl_PackageInitProc*)NULL);
-#endif
-
-#ifdef _GWIN32
- if (Tkwin32_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "win32", Tkwin32_Init,
- (Tcl_PackageInitProc*)NULL);
-#endif
return TCL_OK;
}
-
diff --git a/ds9/ds9.C b/ds9/ds9.windows
similarity index 62%
rename from ds9/ds9.C
rename to ds9/ds9.windows
index 9005192..3b6fcbd 100644
--- a/ds9/ds9.C
+++ b/ds9/ds9.windows
@@ -11,6 +11,8 @@ using namespace std;
#include <tcl.h>
#include <tk.h>
+#define DEBUGS(x) {FILE* fp=fopen("/Users/joye/debug.txt","a+");fprintf(fp,"%s\n",x);fclose(fp);}
+
extern "C" {
int SAOAppInit(Tcl_Interp *interp);
int SAOLocalMainHook(int* argc, char*** argv);
@@ -20,8 +22,7 @@ extern "C" {
int Zvfs_Init(Tcl_Interp*);
int Zvfs_Mount(Tcl_Interp*, char*, char *);
- int Blt_core_Init(Tcl_Interp*);
- int Blt_x_Init(Tcl_Interp*);
+ int Tlt_Init(Tcl_Interp*);
int Tktable_Init(Tcl_Interp*);
int Checkdns_Init(Tcl_Interp*);
int Saotk_Init(Tcl_Interp*);
@@ -45,25 +46,13 @@ extern "C" {
int Tclxml_Init(Tcl_Interp*);
int Tclxml_libxml2_Init(Tcl_Interp*);
-#ifndef _GWIN32
- int Signal_ext_Init(Tcl_Interp*);
-#endif
-
-#ifdef _MACOSX
- int Tkmacosx_Init(Tcl_Interp*);
-#endif
-#ifdef _GWIN32
int Tkwin32_Init(Tcl_Interp*);
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
-
-#endif
}
-static char* appname = NULL;
-char* dupstr(const char* str);
Tcl_Interp *global_interp;
void internalError(const char* msg)
@@ -72,108 +61,37 @@ void internalError(const char* msg)
Tcl_SetVar2(global_interp, "ds9", "msg,level", "error", TCL_GLOBAL_ONLY);
}
-// currently use relative path
-// using full path with spaces causes problems
-// with htmwidget and tcl/tk
-
int SAOLocalMainHook(int* argcPtr, char*** argvPtr)
{
// sync C++ io calls with C io calls
ios::sync_with_stdio();
- // save real application name
- int argc = *argcPtr;
- char** argv = *argvPtr;
- appname = dupstr(argv[0]);
-
- // so that tcl and tk know where to find their libs
- // we do it here before InitLibraryPath is called
- putenv((char*)"TCL_LIBRARY=./zvfsmntpt/tcl8.6");
- putenv((char*)"TK_LIBRARY=./zvfsmntpt/tk8.6");
- // putenv((char*)"TCL_LIBRARY=/tmp/zvfsmntpt/tcl8.6");
- // putenv((char*)"TK_LIBRARY=/tmp/zvfsmntpt/tk8.6");
+ // do this first
+ Tcl_FindExecutable((*argvPtr)[0]);
- // invoke startup script
+ // startup script
Tcl_Obj *path = Tcl_NewStringObj("./zvfsmntpt/src/ds9.tcl",-1);
- // Tcl_Obj *path = Tcl_NewStringObj("/tmp/zvfsmntpt/src/ds9.tcl",-1);
Tcl_SetStartupScript(path, NULL);
}
int SAOAppInit(Tcl_Interp *interp)
{
- // reset argv0
- if (appname) {
- Tcl_SetVar(interp, "argv0", appname, TCL_GLOBAL_ONLY);
- delete [] appname;
- }
-
// save interp for cputs function
global_interp = interp;
- // We have to initialize the virtual filesystem before calling
- // Tcl_Init(). Otherwise, Tcl_Init() will not be able to find
- // its startup script files.
- if (Zvfs_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "zvfs", Zvfs_Init, (Tcl_PackageInitProc*)NULL);
-
- // find current working directory, and set as mount point
- {
- Tcl_DString pwd;
- Tcl_DStringInit(&pwd);
- Tcl_GetCwd(interp, &pwd);
-#ifdef ZIPFILE
- ostringstream str;
-#ifndef _GWIN32
- str << (char *)Tcl_GetNameOfExecutable()
- << ".zip"
- << ends;
-#else
- str << (char *)Tcl_GetNameOfExecutable()
- << "/../ds9.zip"
- << ends;
-#endif
- if( Zvfs_Mount(interp, (char*)str.str().c_str(), Tcl_DStringValue(&pwd)) != TCL_OK ){
- char str[] = "ERROR: Unable to open the auxiliary ds9 file 'ds9.zip'. If you moved the ds9 program from its original location, please also move the zip file to the same place.";
-
-#ifndef _GWIN32
- cerr << str << endl;
-#else
- MessageBox(NULL, str, "SAOImage DS9", MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
-#endif
- exit(1);
- }
-#else
- Zvfs_Mount(interp, (char *)Tcl_GetNameOfExecutable(),
- Tcl_DStringValue(&pwd));
-#endif
- Tcl_DStringFree(&pwd);
- }
-
// Initialize Tcl and Tk
- if (Tcl_Init(interp))
+ if (Tcl_Init(interp) == TCL_ERROR)
return TCL_ERROR;
// Tk
- if (Tk_Init(interp))
+ if (Tk_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage(interp,"Tk", Tk_Init, Tk_SafeInit);
- {
- Tcl_DString pwd;
- Tcl_DStringInit(&pwd);
- Tcl_GetCwd(interp, &pwd);
- Tcl_DStringFree(&pwd);
- }
-
- // Blt
- if (Blt_core_Init(interp) == TCL_ERROR)
+ // tlt
+ if (Tlt_Init(interp) == TCL_ERROR)
return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_core", Blt_core_Init,
- (Tcl_PackageInitProc*)NULL);
- if (Blt_x_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage(interp, "blt_extra", Blt_x_Init,
+ Tcl_StaticPackage(interp, "tlt", Tlt_Init,
(Tcl_PackageInitProc*)NULL);
// Tktable
@@ -282,28 +200,10 @@ int SAOAppInit(Tcl_Interp *interp)
Tcl_StaticPackage (interp, "window", Tkimgwindow_Init,
(Tcl_PackageInitProc*)NULL);
- // Signal_Ext
-#ifndef _GWIN32
- if (Signal_ext_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "signal", Signal_ext_Init,
- (Tcl_PackageInitProc*)NULL);
-#endif
-
-#ifdef _MACOSX
- if (Tkmacosx_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- Tcl_StaticPackage (interp, "macosx", Tkmacosx_Init,
- (Tcl_PackageInitProc*)NULL);
-#endif
-
-#ifdef _GWIN32
if (Tkwin32_Init(interp) == TCL_ERROR)
return TCL_ERROR;
Tcl_StaticPackage (interp, "win32", Tkwin32_Init,
(Tcl_PackageInitProc*)NULL);
-#endif
return TCL_OK;
}
-
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Info.plist b/ds9/macosx/SAOImage DS9.app.old/Contents/Info.plist
similarity index 98%
copy from ds9/macosx/SAOImage DS9.app/Contents/Info.plist
copy to ds9/macosx/SAOImage DS9.app.old/Contents/Info.plist
index 9bc2e76..a93e9ad 100644
--- a/ds9/macosx/SAOImage DS9.app/Contents/Info.plist
+++ b/ds9/macosx/SAOImage DS9.app.old/Contents/Info.plist
@@ -53,7 +53,7 @@
<key>CFBundleSignature</key>
<string>DS9 </string>
<key>CFBundleVersion</key>
- <string>7.3b2</string>
+ <string>7.3b3</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSMinimumSystemVersion</key>
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/MacOS/ds9 b/ds9/macosx/SAOImage DS9.app.old/Contents/MacOS/ds9
similarity index 100%
rename from ds9/macosx/SAOImage DS9.app/Contents/MacOS/ds9
rename to ds9/macosx/SAOImage DS9.app.old/Contents/MacOS/ds9
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/PkgInfo b/ds9/macosx/SAOImage DS9.app.old/Contents/PkgInfo
similarity index 100%
rename from ds9/macosx/SAOImage DS9.app/Contents/PkgInfo
rename to ds9/macosx/SAOImage DS9.app.old/Contents/PkgInfo
diff --git a/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/App.icns b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/App.icns
new file mode 100644
index 0000000..bf30e38
Binary files /dev/null and b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/App.icns differ
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/InfoPlist.strings b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/InfoPlist.strings
similarity index 93%
rename from ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/InfoPlist.strings
rename to ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/InfoPlist.strings
index 0891356..ae42b9e 100644
Binary files a/ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/InfoPlist.strings and b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/InfoPlist.strings differ
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/classes.nib b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/classes.nib
similarity index 100%
rename from ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/classes.nib
rename to ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/classes.nib
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/info.nib b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/info.nib
similarity index 100%
rename from ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/info.nib
rename to ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/info.nib
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/objects.xib b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/objects.xib
similarity index 100%
rename from ds9/macosx/SAOImage DS9.app/Contents/Resources/English.lproj/main.nib/objects.xib
rename to ds9/macosx/SAOImage DS9.app.old/Contents/Resources/English.lproj/main.nib/objects.xib
diff --git a/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/fits.icns b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/fits.icns
new file mode 100644
index 0000000..0afa214
Binary files /dev/null and b/ds9/macosx/SAOImage DS9.app.old/Contents/Resources/fits.icns differ
diff --git a/ds9/macosx/SAOImage DS9.app/Contents/Info.plist b/ds9/macosx/SAOImage DS9.app/Contents/Info.plist
index 9bc2e76..b942b78 100644
--- a/ds9/macosx/SAOImage DS9.app/Contents/Info.plist
+++ b/ds9/macosx/SAOImage DS9.app/Contents/Info.plist
@@ -30,34 +30,34 @@
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
- <key>LSTypeIsPackage</key>
- <false/>
- <key>NSDocumentClass</key>
- <string>FITSData</string>
- <key>NSPersistentStoreTypeKey</key>
- <string>Binary</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>ds9</string>
+ <key>CFBundleGetInfoString</key>
+ <string>"SAOImage DS9 7.3
+Copyright 1999-2013
+Smithsonian Astrophysical Observatory"</string>
<key>CFBundleIconFile</key>
- <string>App</string>
+ <string>App.icns</string>
<key>CFBundleIdentifier</key>
<string>com.sao.SAOImageDS9</string>
<key>CFBundleInfoDictionaryVersion</key>
- <string>7.1</string>
+ <string>6.0</string>
<key>CFBundleName</key>
<string>SAOImage DS9</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>7.3</string>
<key>CFBundleSignature</key>
- <string>DS9 </string>
+ <string>DS9</string>
<key>CFBundleVersion</key>
- <string>7.3b2</string>
- <key>CSResourcesFileMapped</key>
- <true/>
+ <string>7.3</string>
<key>LSMinimumSystemVersion</key>
- <string>10.4.0</string>
+ <string>10.5.0</string>
+ <key>LSRequiresCarbon</key>
+ <true/>
<key>LSEnvironment</key>
<dict>
<key>PATH</key>
diff --git a/ds9/win/ds9.rc b/ds9/win/ds9.rc
index 3678485..ae4c940 100644
--- a/ds9/win/ds9.rc
+++ b/ds9/win/ds9.rc
@@ -1,6 +1,6 @@
#include <windows.h>
-#define VV "7.3b2"
+#define VV "7.3b3"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 7,3,0,0
diff --git a/macosx/Makefile b/macosx/Makefile
index 9ece3c4..3a6be7b 100644
--- a/macosx/Makefile
+++ b/macosx/Makefile
@@ -5,18 +5,20 @@ include ../make.pkgs
CXXFLAGS = $(CXXOPT) \
-I../include \
-I../saotk/vector \
+ -I../saotk/widget \
-I../$(TKDIR)/generic \
-I../$(TKDIR)/macosx \
-I$(X11INCLUDE)
-SRC = tkmacosx.C \
- macosxlib.C \
- xxlib.C \
+SRC = \
+ macosxlib.mm \
+ rotstr.mm \
+ tkmacosx.mm \
+ xxlib.mm
-OBJS = $(SRC:%.C=%.o)
+OBJS = $(SRC:%.mm=%.o)
-INCLS = macosxlib.h \
- xxlib.h
+INCLS = macosxlib.h xxlib.h rotstr.h
LIB = libxxlib.a
@@ -37,11 +39,5 @@ distclean : clean
FORCE :
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
+%.o: %.mm
+ $(COMPILE.C) $(OUTPUT_OPTION) $<
diff --git a/macosx/macosxlib.h b/macosx/macosxlib.h
index e9e16bb..51586ce 100644
--- a/macosx/macosxlib.h
+++ b/macosx/macosxlib.h
@@ -5,6 +5,9 @@
#ifndef __macosxlib_h__
#define __macosxlib_h__
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
#include "vector.h"
void macosxBegin();
@@ -27,7 +30,4 @@ void macosxFillPolygon(Vector*, int);
void macosxBitmapCreate(void*, int, int, const Vector&, const Vector&);
-void macosxGetMasks(unsigned long* red, unsigned long* green,
- unsigned long* blue);
-
#endif
diff --git a/macosx/macosxlib.C b/macosx/macosxlib.mm
similarity index 94%
rename from macosx/macosxlib.C
rename to macosx/macosxlib.mm
index 53a0095..563177f 100644
--- a/macosx/macosxlib.C
+++ b/macosx/macosxlib.mm
@@ -156,10 +156,3 @@ void macosxBitmapCreate(void* img, int width, int height,
tkmacosx->bitmapCreate(img, width, height, vv1[0], vv1[1], ss[0], ss[1]);
}
}
-
-void macosxGetMasks(unsigned long* red, unsigned long* green,
- unsigned long* blue, unsigned long* alpha)
-{
- if (tkmacosx)
- tkmacosx->getMasks(red,green,blue,alpha);
-}
diff --git a/unix/rotstr.h b/macosx/rotstr.h
similarity index 59%
copy from unix/rotstr.h
copy to macosx/rotstr.h
index 5623831..5a4db57 100644
--- a/unix/rotstr.h
+++ b/macosx/rotstr.h
@@ -7,9 +7,8 @@
#include <tk.h>
-class Widget;
class Vector;
-extern void XDrawRotString(Display* display, Drawable drawable, GC gc,
- Vector&, double angle, const char* text,
- Tk_Font font, Widget* parent);
+void XDrawRotString(Display* display, Drawable drawable, GC gc,
+ Vector& v, double angle, const char* text,
+ Tk_Font font);
#endif
diff --git a/macosx/rotstr.mm b/macosx/rotstr.mm
new file mode 100644
index 0000000..bac7510
--- /dev/null
+++ b/macosx/rotstr.mm
@@ -0,0 +1,52 @@
+// Copyright (C) 1999-2013
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tkMacOSXPrivate.h>
+#include <tkMacOSXFont.h>
+
+#include "vector.h"
+
+void XDrawRotString(Display* display, Drawable drawable, GC gc,
+ Vector& v, double angle, const char* text,
+ Tk_Font font)
+{
+ MacDrawable* macWin = (MacDrawable*)drawable;
+
+ TkMacOSXDrawingContext dc;
+ TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc);
+
+ // undo the xform in TkMacOSXSetupDrawingContext
+ CGContextConcatCTM(dc.context, CGAffineTransformMake(1.0, 0.0, 0.0,
+ -1.0, 0.0, dc.portBounds.size.height));
+
+ CGAffineTransform mm = CGAffineTransformMakeRotation(angle);
+ CGContextSetTextMatrix(dc.context, mm);
+
+ // map to window space
+ Vector center =
+ Vector(dc.portBounds.size.width/2., dc.portBounds.size.height/2.);
+ Vector vv = v *
+ Translate(-center) *
+ Translate(macWin->xOff, macWin->yOff) *
+ FlipY() *
+ Translate(center);
+
+ // draw it
+ TkFont* fontPtr = (TkFont*)font;
+ Tcl_DString ds;
+ Tcl_DStringInit(&ds);
+ int size = Tk_PostscriptFontName(font, &ds);
+ CGContextSelectFont(dc.context, Tcl_DStringValue(&ds),
+ size, kCGEncodingMacRoman);
+ Tcl_DStringFree(&ds);
+ CGContextShowTextAtPoint (dc.context, vv[0], vv[1], text, strlen(text));
+
+ // done
+ TkMacOSXRestoreDrawingContext(&dc);
+}
diff --git a/macosx/tkmacosx.h b/macosx/tkmacosx.h
index 0d6daf5..d891c44 100644
--- a/macosx/tkmacosx.h
+++ b/macosx/tkmacosx.h
@@ -5,8 +5,8 @@
#ifndef __tkmacosx_h__
#define __tkmacosx_h__
-#include <tk.h>
-#include <Carbon/Carbon.h>
+#include <tcl.h>
+#include <tkMacOSXPrivate.h>
#include "vector.h"
@@ -17,10 +17,10 @@ class TkMacosx {
int showDialog;
OSStatus status;
+ CGContextRef context;
PMPageFormat pageFormat;
PMPrintSettings printSettings;
PMPrintSession printSession;
- CGContextRef context;
Matrix canvasToPage;
@@ -58,9 +58,6 @@ class TkMacosx {
void fillPolygon(float*, float*, int);
void bitmapCreate(void*, int, int, float, float, float, float);
-
- void getMasks(unsigned long* red, unsigned long* green,
- unsigned long* blue, unsigned long* alpha);
};
extern TkMacosx* tkmacosx;
diff --git a/macosx/tkmacosx.C b/macosx/tkmacosx.mm
similarity index 89%
rename from macosx/tkmacosx.C
rename to macosx/tkmacosx.mm
index 90bfc6a..6be209b 100644
--- a/macosx/tkmacosx.C
+++ b/macosx/tkmacosx.mm
@@ -8,11 +8,9 @@ using namespace std;
#include <string.h>
-#include "tkmacosx.h"
-
-#include <tkMacOSX.h>
-#include <tkMacOSXInt.h>
+#include <tkMacOSXPrivate.h>
+#include "tkmacosx.h"
extern "C" {
int Tkmacosx_Init(Tcl_Interp* interp);
@@ -178,6 +176,7 @@ int TkMacosx::pmPrintBegin(int argc, const char* argv[])
Vector canvas(width,height);
+ /*
// print session
status = PMCreateSession(&printSession);
if (status != noErr)
@@ -347,10 +346,12 @@ int TkMacosx::pmPrintBegin(int argc, const char* argv[])
error:
cerr << "PM Error Code: " << status << endl;
return TCL_ERROR;
+ */
}
int TkMacosx::pmPrintEnd()
{
+ /*
status = PMSessionEndPage(printSession);
if (status != noErr)
goto error;
@@ -372,6 +373,7 @@ int TkMacosx::pmPrintEnd()
PMRelease(printSession);
printSession = NULL;
return TCL_ERROR;
+ */
}
int TkMacosx::pmPrintText(int argc, const char* argv[])
@@ -407,6 +409,7 @@ int TkMacosx::pmPrintText(int argc, const char* argv[])
return TCL_ERROR;
}
+ /*
if (!argv[4])
goto error;
@@ -639,10 +642,12 @@ int TkMacosx::pmPrintText(int argc, const char* argv[])
delete sstr;
return TCL_ERROR;
+ */
}
int TkMacosx::pmPageSetup()
{
+ /*
// print session
status = PMCreateSession(&printSession);
if (status != noErr)
@@ -682,6 +687,7 @@ int TkMacosx::pmPageSetup()
PMRelease(printSession);
printSession = NULL;
return TCL_ERROR;
+ */
}
// drawing routines
@@ -709,7 +715,7 @@ void TkMacosx::width(float ww)
void TkMacosx::dash(float* dd, int nn)
{
- CGContextSetLineDash(context,0,dd,nn);
+ CGContextSetLineDash(context,0,(CGFloat*)dd,nn);
}
void TkMacosx::font(const char* font, float size)
@@ -797,95 +803,3 @@ void TkMacosx::bitmapCreate(void* data, int width, int height,
if (cs)
CGColorSpaceRelease(cs);
}
-
-void TkMacosx::getMasks(unsigned long* red, unsigned long* green,
- unsigned long* blue, unsigned long* alpha)
-{
- // init
- *red = 0;
- *blue = 0;
- *green = 0;
- *alpha = 0;
-
- Tk_Window tkwin = Tk_MainWindow(interp);
- if (!tkwin)
- return;
-
- TkWindowPrivate* ptr = ((TkWindow *) (tkwin))->privatePtr;
- if (!ptr)
- return;
-
- GWorldPtr gw = ptr->grafPtr;
- if (!gw)
- return;
-
- PixMapHandle ph = GetGWorldPixMap(gw);
- if (!ph)
- return;
-
- PixMap* pm = *ph;
- switch (pm->pixelFormat) {
- case k16BE555PixelFormat: // 0x10
- *red = 0x00007C00;
- *green = 0x000003E0;
- *blue = 0x0000001F;
- *alpha = 0x00000000;
- return;
- case k16LE555PixelFormat: // 'L555'
- *red = 0x00007C00;
- *green = 0x000003E0;
- *blue = 0x0000001F;
- *alpha = 0x00000000;
- return;
- case k16BE565PixelFormat: // 'B565'
- *red = 0x0000F800;
- *green = 0x000007E0;
- *blue = 0x0000001F;
- *alpha = 0x00000000;
- return;
- case k16LE565PixelFormat: // 'L565'
- *red = 0x0000F800;
- *green = 0x000007E0;
- *blue = 0x0000001F;
- *alpha = 0x00000000;
- return;
-
- case k24RGBPixelFormat: // 0x18
- *red = 0x00FF0000;
- *green = 0x0000FF00;
- *blue = 0x000000FF;
- *alpha = 0x00000000;
- return;
- case k24BGRPixelFormat: // '24BG'
- *red = 0x00FF0000;
- *green = 0x0000FF00;
- *blue = 0x000000FF;
- *alpha = 0x00000000;
- return;
-
- case k32ARGBPixelFormat: // 0x20
- *alpha = 0xFF000000;
- *red = 0x00FF0000;
- *green = 0x0000FF00;
- *blue = 0x000000FF;
- return;
- case k32BGRAPixelFormat: // 'BGRA'
- *alpha = 0xFF000000;
- *red = 0x00FF0000;
- *green = 0x0000FF00;
- *blue = 0x000000FF;
- return;
- case k32ABGRPixelFormat: // 'ABGR'
- *red = 0x000000FF;
- *green = 0x0000FF00;
- *blue = 0x00FF0000;
- *alpha = 0xFF000000;
- return;
- case k32RGBAPixelFormat: // 'RGBA'
- *red = 0x000000FF;
- *green = 0x0000FF00;
- *blue = 0x00FF0000;
- *alpha = 0xFF000000;
- return;
- }
-}
diff --git a/macosx/xxlib.C b/macosx/xxlib.C
deleted file mode 100644
index 96e2f83..0000000
--- a/macosx/xxlib.C
+++ /dev/null
@@ -1,336 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-using namespace std;
-
-#include <tcl.h>
-#include <tk.h>
-#include <Xlib.h>
-
-#include <tkMacOSX.h>
-#include <tkMacOSXInt.h>
-#include <tkMacOSXFont.h>
-#include <tkMacOSXPrivate.h>
-
-#include "vector.h"
-
-#define RGBFLOATRED(c) ((c).red / 65535.0)
-#define RGBFLOATGREEN(c) ((c).green / 65535.0)
-#define RGBFLOATBLUE(c) ((c).blue / 65535.0)
-
-char* XImageData(XImage* ximage)
-{
- GWorldPtr gw = TkMacOSXGetDrawablePort((Pixmap)(ximage->obdata));
- PixMapHandle ph = GetGWorldPixMap(gw);
- PixMap* pm = *ph;
- return GetPixBaseAddr(ph);
-}
-
-void DrawRotString(Display* display, Drawable drawable, GC gc, Tk_Font font,
- double angle, const Vector& v, const char* text,
- Widget* parent)
-{
- MacDrawable* macWin = (MacDrawable*)drawable;
-
- TkMacOSXDrawingContext dc;
- TkMacOSXSetupDrawingContext(drawable, gc, 1, &dc);
-
- // undo the xform in TkMacOSXSetupDrawingContext
- CGContextConcatCTM(dc.context, CGAffineTransformMake(1.0, 0.0, 0.0,
- -1.0, 0.0, dc.portBounds.bottom - dc.portBounds.top));
-
- CGAffineTransform mm = CGAffineTransformMakeRotation(angle);
- CGContextSetTextMatrix(dc.context, mm);
-
- // map to window space
- Vector center =
- Vector((dc.portBounds.right-dc.portBounds.left)/2.,
- (dc.portBounds.bottom-dc.portBounds.top)/2.);
- Vector vv = v *
- Translate(-center) *
- Translate(macWin->xOff, macWin->yOff) *
- FlipY() *
- Translate(center);
-
- // draw it
- TkFont* fontPtr = (TkFont*)font;
- Tcl_DString ds;
- Tcl_DStringInit(&ds);
- int size = Tk_PostscriptFontName(font, &ds);
- CGContextSelectFont(dc.context, Tcl_DStringValue(&ds),
- size, kCGEncodingMacRoman);
- Tcl_DStringFree(&ds);
- CGContextShowTextAtPoint (dc.context, vv[0], vv[1], text, strlen(text));
-
- // done
- TkMacOSXRestoreDrawingContext(&dc);
-}
-
-extern "C" {
- void XDrawString(Display* display, Drawable drawable, GC gc,
- int x, int y, _Xconst char* str, int length)
- {
- DrawRotString(display, drawable, gc, (Tk_Font)gc->font, 0,
- Vector(x,y), str);
- //Tk_DrawChars(display, drawable, gc, (Tk_Font)gc->font, str, length, x, y);
- }
-
- // Pixmap Suite
- Pixmap XCreatePixmap(Display* display, Drawable drawable,
- unsigned int width, unsigned int height,
- unsigned int depth)
- {
- Tk_GetPixmap(display, drawable, width, height, depth);
- }
-
- // XImage Suite
- XImage* XXCreateImage(Display* display, Visual* visual,
- unsigned int depth, int format, int offset,
- char* data, unsigned int width, unsigned int height,
- int bitmap_pad, int bytes_per_line)
- {
- XImage* ximage = XCreateImage(display, visual, depth, format, offset,
- data, width, height,
- bitmap_pad, bytes_per_line);
-
- GWorldPtr gw = (GWorldPtr)data;
- PixMapHandle ph = GetGWorldPixMap(gw);
- PixMap* pm = *ph;
-
- // now correct it
- ximage->bytes_per_line = (pm->rowBytes & 0x3fff);
-
- switch (depth) {
- case 1:
- ximage->bits_per_pixel = 1;
- ximage->bitmap_unit = 8;
- ximage->bitmap_pad = 1;
- break;
- case 8:
- ximage->bits_per_pixel = 8;
- ximage->bitmap_unit = 8;
- ximage->bitmap_pad = 8;
- break;
- case 15:
- ximage->bits_per_pixel = 16;
- ximage->bitmap_unit = 32;
- ximage->bitmap_pad = 32;
- break;
- case 16:
- ximage->bits_per_pixel = 16;
- ximage->bitmap_unit = 32;
- ximage->bitmap_pad = 32;
- break;
- case 24:
- ximage->bits_per_pixel = 24;
- ximage->bitmap_unit = 32;
- ximage->bitmap_pad = 32;
- break;
- case 32:
- ximage->bits_per_pixel = 32;
- ximage->bitmap_unit = 32;
- ximage->bitmap_pad = 32;
- break;
- }
-
- switch (pm->pixelFormat) {
- case k16BE555PixelFormat: // 0x10
- ximage->bitmap_bit_order = MSBFirst;
- ximage->byte_order = MSBFirst;
- break;
- case k16LE555PixelFormat: // 'L555'
- ximage->bitmap_bit_order = LSBFirst;
- ximage->byte_order = LSBFirst;
- break;
- case k16BE565PixelFormat: // 'B565'
- ximage->bitmap_bit_order = MSBFirst;
- ximage->byte_order = MSBFirst;
- break;
- case k16LE565PixelFormat: // 'L565'
- ximage->bitmap_bit_order = LSBFirst;
- ximage->byte_order = LSBFirst;
- break;
-
- case k24RGBPixelFormat: // 0x18
- ximage->bitmap_bit_order = MSBFirst;
- ximage->byte_order = MSBFirst;
- break;
- case k24BGRPixelFormat: // '24BG'
- ximage->bitmap_bit_order = LSBFirst;
- ximage->byte_order = LSBFirst;
- break;
-
- case k32ARGBPixelFormat: // 0x20
- ximage->bitmap_bit_order = MSBFirst;
- ximage->byte_order = MSBFirst;
- break;
- case k32BGRAPixelFormat: // 'BGRA'
- ximage->bitmap_bit_order = LSBFirst;
- ximage->byte_order = LSBFirst;
- break;
- case k32ABGRPixelFormat: // 'ABGR'
- ximage->bitmap_bit_order = MSBFirst;
- ximage->byte_order = MSBFirst;
- break;
- case k32RGBAPixelFormat: // 'RGBA'
- ximage->bitmap_bit_order = LSBFirst;
- ximage->byte_order = LSBFirst;
- break;
-
- default:
- cerr << "MacOSX Internal Error: XXCreateImage: pixelFormat " << hex << pm->pixelFormat
- << " not implemented" << endl;
- break;
- }
-
- return ximage;
- }
-
- XImage *XXGetImage(Display *display, Drawable drawable,
- int x, int y,
- unsigned int width, unsigned int height,
- unsigned long plane_mask, int format)
- {
- if (width ==0 || height ==0) {
- cerr << "MacOSX Internal Error: XXGetImage: width/height is zero" << endl;
- return NULL;
- }
-
- if (format != ZPixmap) {
- cerr << "MacOSX Internal Error: XXGetImage: illegal format" << endl;
- return NULL;
- }
-
- if (!TkMacOSXGetDrawablePort(drawable)) {
- cerr << "MacOSX Internal Error: XXGetImage: bad drawable" << endl;
- return NULL;
- }
-
- // get pixmap
- Pixmap pixmap = Tk_GetPixmap(display, drawable, width, height, 32);
- if (!pixmap) {
- cerr << "MacOSX Internal Error: XXGetImage: bad pixmap" << endl;
- return NULL;
- }
-
- // get gc
- GC gc;
- Tk_Window win = (Tk_Window)((MacDrawable *) drawable)->winPtr;
- if (win) {
- XGCValues values;
- gc = Tk_GetGC(win, 0, &values);
- }
- else
- gc = XCreateGC(display, pixmap, 0, NULL);
-
- // populate pixmap
- XCopyArea(display, drawable, pixmap, gc, x, y, width, height, 0, 0);
-
- if (win)
- Tk_FreeGC(display, gc);
- else
- XFreeGC(display, gc);
-
- GWorldPtr gw = TkMacOSXGetDrawablePort(pixmap);
- PixMapHandle ph = GetGWorldPixMap(gw);
- PixMap* pm = *ph;
-
- int depth = pm->pixelSize;
- int bitmap_pad = depth; // will be reset
- int bytes_per_line = width; // will be reset
- XImage* image = XXCreateImage(display, NULL, depth, format, 0,
- (char*)TkMacOSXGetDrawablePort(pixmap),
- width, height,
- bitmap_pad, bytes_per_line);
- // needed by tk
- image->obdata = (XPointer)pixmap;
-
- return image;
- }
-
- void XSetClipRectangles(Display* display, GC gc, int clip_x_origin,
- int clip_y_origin, XRectangle* r,
- int n, int ordering)
- {
- // clear it
- TkpClipMask *clip_mask = (TkpClipMask*)gc->clip_mask;
- if (clip_mask && clip_mask->type == TKP_CLIP_REGION)
- TkpReleaseRegion(clip_mask->value.region);
-
- // new region
- TkRegion clipRgn = TkCreateRegion();
-
- // clip origin not used, but set anyways
- gc->clip_x_origin = clip_x_origin;
- gc->clip_y_origin = clip_y_origin;
-
- for (int ii =0; ii<n; ii++)
- TkUnionRectWithRegion(&r[ii], clipRgn, clipRgn);
-
- // and set it
- TkSetRegion(display, gc, clipRgn);
- }
-
- Bool XXQueryPointer(Display* display, Window w,
- Window* root_return, Window* child_return,
- int* root_x_return, int* root_y_return,
- int* win_x_return, int* win_y_return,
- unsigned int* mask_return)
- {
- XQueryPointer(display, w, root_return, child_return,
- root_x_return, root_y_return,
- win_x_return, win_y_return, mask_return);
-
- // flag root for XXWarpPointer
- *root_return = 1;
- *child_return = NULL;
- }
-
- void XXWarpPointer(Display* display, Window src_w, Window dest_w,
- int src_x, int src_y,
- unsigned int src_width, unsigned int src_height,
- int dest_x, int dest_y)
- {
- // we have a special mode, root=1, from XXQueryPointer
- CGPoint pt;
-
- if (dest_w == None) {
- Point ppt;
- GetGlobalMouse(&ppt);
- pt.x = dest_x+ppt.h;
- pt.y = dest_y+ppt.v;
- }
- else if (dest_w == 1) {
- pt.x = dest_x;
- pt.y = dest_y;
- }
- else {
- Point ppt;
- MacDrawable* macPtr = (MacDrawable*)dest_w;
- ppt.h = dest_x+macPtr->xOff;
- ppt.v = dest_y+macPtr->yOff;
-
- CGrafPtr port = TkMacOSXGetDrawablePort(dest_w);
- QDLocalToGlobalPoint(port, &ppt);
- pt.x = ppt.h;
- pt.y = ppt.v;
- }
-
- // we can't use the following, we want a mouse event generated.
- // CGWarpMouseCursorPosition(pt);
- // and we can't use the following, its buggy as all get out
- // CGPostMouseEvent(pt, true, 1, false);
-
- CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
- CGEventRef ev = CGEventCreateMouseEvent(src,kCGEventMouseMoved,pt,kCGMouseButtonLeft);
- // bug in tiger, reset event type
- CGEventSetType(ev,kCGEventMouseMoved);
- CGEventPost(kCGSessionEventTap,ev);
- CFRelease(ev);
- CFRelease(src);
- }
-}
diff --git a/macosx/xxlib.h b/macosx/xxlib.h
index cb81817..6f33e60 100644
--- a/macosx/xxlib.h
+++ b/macosx/xxlib.h
@@ -5,22 +5,15 @@
#ifndef __xxlib_h__
#define __xxlib_h__
-#include <tcl.h>
#include <tk.h>
-// direct X11 to Tk
-
-char* XImageData(XImage* ximage);
-
extern "C" {
- // available in blt/src/bltMacOSX.c
+ // New Routines
void XPutImage(Display* display, Drawable d, GC gc, XImage* image,
int src_x, int src_y, int dest_x, int dest_y,
unsigned int width, unsigned int height);
- void XFreePixmap(Display*, Pixmap);
- // New Routines
void XDrawString(Display* display, Drawable drawable, GC gc,
int x, int y, _Xconst char* str, int length);
@@ -28,21 +21,32 @@ extern "C" {
unsigned int width, unsigned int height,
unsigned int depth);
- void XSetClipRectangles(Display* display, GC gc, int clip_x_origin,
- int clip_y_origin, XRectangle* r,
- int n, int ordering);
+ // blt only
+ void XDrawArcs(Display *display, Drawable d, GC gc, XArc *arcArr, int nArcs);
- // Redefined Routines
- XImage *XXGetImage(Display *display, Drawable drawable, int x, int y,
- unsigned int width, unsigned int height,
- unsigned long plane_mask, int format);
+ void XDrawRectangles(Display *display, Drawable drawable, GC gc,
+ XRectangle *rectArr, int nRects);
+ void XFillArcs(Display *display, Drawable d, GC gc, XArc *arcArr, int nArcs);
+
+ int XFree(void *data);
+ long XExtendedMaxRequestSize(Display *display);
+ int XFreeFontNames(char *list[]);
+ char **XListFonts(Display *display, char *pattern, int maxnames,
+ int *actual_count_return);
+ long XMaxRequestSize(Display *display);
+
+ // defined in tk/macosx
+ int XSetClipRectangles(Display *d, GC gc, int clip_x_origin,
+ int clip_y_origin, XRectangle* rectangles,
+ int n, int ordering);
+
+ // Redefined Routines
Bool XXQueryPointer(Display* display, Window w,
Window* root_return, Window* child_return,
int* root_x_return, int* root_y_return,
int* win_x_return, int* win_y_return,
unsigned int* mask_return);
-
void XXWarpPointer(Display* display, Window src_w, Window dest_w,
int src_x, int src_y,
unsigned int src_width, unsigned int src_height,
diff --git a/macosx/xxlib.mm b/macosx/xxlib.mm
new file mode 100644
index 0000000..a99cd18
--- /dev/null
+++ b/macosx/xxlib.mm
@@ -0,0 +1,142 @@
+// Copyright (C) 1999-2012
+// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
+// For conditions of distribution and use, see copyright notice in "copyright"
+
+#include <iostream>
+#include <sstream>
+#include <iomanip>
+using namespace std;
+
+#include <tkMacOSXPrivate.h>
+// we need real versions of these
+#undef XFree
+#undef XFlush
+
+#include <tk.h>
+#include <tkInt.h>
+#include <X11/Xlib.h>
+
+#include "widget.h"
+#include "vector.h"
+#include "rotstr.h"
+
+#define RGBFLOATRED(c) ((c).red / 65535.0)
+#define RGBFLOATGREEN(c) ((c).green / 65535.0)
+#define RGBFLOATBLUE(c) ((c).blue / 65535.0)
+
+extern "C" {
+ void XPutImage(Display* display, Drawable d, GC gc, XImage* image,
+ int src_x, int src_y, int dest_x, int dest_y,
+ unsigned int width, unsigned int height)
+ {
+ TkPutImage(NULL, 0, display, d, gc, image, src_x, src_y,
+ dest_x, dest_y, width, height);
+ }
+
+ void XDrawString(Display* display, Drawable drawable, GC gc,
+ int x, int y, _Xconst char* str, int length)
+ {
+ Vector vv(x,y);
+ XDrawRotString(display, drawable, gc, vv, 0, str, (Tk_Font)gc->font);
+ }
+
+ Pixmap XCreatePixmap(Display* display, Drawable drawable,
+ unsigned int width, unsigned int height,
+ unsigned int depth)
+ {
+ Tk_GetPixmap(display, drawable, width, height, depth);
+ }
+
+ /*
+ void XSetClipRectangles(Display* display, GC gc, int clip_x_origin,
+ int clip_y_origin, XRectangle* r,
+ int n, int ordering)
+ {
+ // clear it
+ TkpClipMask *clip_mask = (TkpClipMask*)gc->clip_mask;
+ if (clip_mask && clip_mask->type == TKP_CLIP_REGION)
+ TkpReleaseRegion(clip_mask->value.region);
+
+ // new region
+ TkRegion clipRgn = TkCreateRegion();
+
+ // clip origin not used, but set anyways
+ gc->clip_x_origin = clip_x_origin;
+ gc->clip_y_origin = clip_y_origin;
+
+ for (int ii =0; ii<n; ii++)
+ TkUnionRectWithRegion(&r[ii], clipRgn, clipRgn);
+
+ // and set it
+ TkSetRegion(display, gc, clipRgn);
+ }
+ */
+
+ // blt only
+ int XFree(void* data)
+ {
+ if (data != NULL)
+ ckfree(data);
+ return 0;
+ }
+
+ // blt only (not implemented)
+ char **XListFonts(Display *display, char *pattern, int maxnames, int *cnt)
+ {
+ *cnt =0;
+ return NULL;
+ }
+
+ int XFreeFontNames(char *list[])
+ {
+ return 0;
+ }
+
+ // blt only (no ops)
+ int XFlush(Display *display) {return 0;}
+ long XExtendedMaxRequestSize(Display *display) {return 0;}
+
+ // Redefined Routines
+ Bool XXQueryPointer(Display* display, Window w,
+ Window* root_return, Window* child_return,
+ int* root_x_return, int* root_y_return,
+ int* win_x_return, int* win_y_return,
+ unsigned int* mask_return)
+ {
+ XQueryPointer(display, w, root_return, child_return,
+ root_x_return, root_y_return,
+ win_x_return, win_y_return, mask_return);
+
+ // flag root for XXWarpPointer
+ *root_return = 1;
+ *child_return = NULL;
+ }
+
+ void XXWarpPointer(Display* display, Window src_w, Window dest_w,
+ int src_x, int src_y,
+ unsigned int src_width, unsigned int src_height,
+ int dest_x, int dest_y)
+ {
+ // we have a special mode, root=1, from XXQueryPointer
+ CGPoint pt;
+
+ if (dest_w == 1) {
+ pt.x = dest_x;
+ pt.y = dest_y;
+ }
+ else {
+ int xx, yy;
+ XQueryPointer(display, dest_w, NULL, NULL, &xx, &yy, NULL, NULL, NULL);
+ pt.x = xx+dest_x;
+ pt.y = yy+dest_y;
+ }
+
+ CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
+ CGEventRef ev = CGEventCreateMouseEvent(src,kCGEventMouseMoved,pt,kCGMouseButtonLeft);
+ CGEventPost(kCGSessionEventTap,ev);
+ CFRelease(ev);
+ CFRelease(src);
+ }
+}
+
+
diff --git a/make.cygwin b/make.cygwin
index ef76371..f59ba78 100644
--- a/make.cygwin
+++ b/make.cygwin
@@ -4,14 +4,14 @@ ARCH = cygwin
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11
-XX = -O2
+XX =
YY = -g
ZZ =
AA = -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
diff --git a/make.darwin64x86lion b/make.darwin64x86lion
index 1efcd1d..7d87a70 100644
--- a/make.darwin64x86lion
+++ b/make.darwin64x86lion
@@ -5,16 +5,15 @@ ARCH = darwin64x86lion
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -m64 -arch x86_64 -mmacosx-version-min=10.7
+ZZ = -m64
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D__M64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -31,6 +30,7 @@ CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+TCLFLAGS= --disable-corefoundation --enable-64bit
ASTFLAGS = star_cv_cnf_trail_type=long
JOBS = 4
diff --git a/make.darwin64x86mountainlion b/make.darwin64x86mountainlion
index 5e5c8f4..940161f 100644
--- a/make.darwin64x86mountainlion
+++ b/make.darwin64x86mountainlion
@@ -5,16 +5,17 @@ ARCH = darwin64x86mountainlion
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+# mpeg segv's with -O
+#XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -m64 -arch x86_64 -mmacosx-version-min=10.8
+ZZ = -m64
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D__M64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -31,6 +32,7 @@ CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+TCLFLAGS= --disable-corefoundation --enable-64bit
ASTFLAGS = star_cv_cnf_trail_type=long
JOBS = 4
diff --git a/make.darwin64x86snowleopard b/make.darwin64x86snowleopard
index bb35bec..e19085d 100644
--- a/make.darwin64x86snowleopard
+++ b/make.darwin64x86snowleopard
@@ -3,16 +3,15 @@ ARCH = darwin64x86snowleopard
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -m64 -arch x86_64
+ZZ = -m64
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D__M64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -29,5 +28,6 @@ CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+TCLFLAGS= --disable-corefoundation --enable-64bit
ASTFLAGS = star_cv_cnf_trail_type=long
JOBS = 4
diff --git a/make.darwinx86lion b/make.darwinx86lion
index 50e378c..9a9da18 100644
--- a/make.darwinx86lion
+++ b/make.darwinx86lion
@@ -5,16 +5,15 @@ ARCH = darwinx86lion
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -arch i386 -mmacosx-version-min=10.7
+ZZ = -m32
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -30,4 +29,6 @@ ZCAT = gzcat
CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+
+TCLFLAGS= --disable-corefoundation
JOBS = 4
diff --git a/make.darwinx86mountainlion b/make.darwinx86mountainlion
index b5927b2..a930417 100644
--- a/make.darwinx86mountainlion
+++ b/make.darwinx86mountainlion
@@ -5,16 +5,15 @@ ARCH = darwinx86mountainlion
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -arch i386 -mmacosx-version-min=10.8
+ZZ = -m32
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -30,4 +29,6 @@ ZCAT = gzcat
CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+
+TCLFLAGS= --disable-corefoundation
JOBS = 4
diff --git a/make.darwinx86snowleopard b/make.darwinx86snowleopard
index 9c6b85e..e2a6fff 100644
--- a/make.darwinx86snowleopard
+++ b/make.darwinx86snowleopard
@@ -3,16 +3,15 @@ ARCH = darwinx86snowleopard
X11INCLUDE=/usr/X11/include
X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -arch i386
+ZZ = -m32
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -28,4 +27,6 @@ ZCAT = gzcat
CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+
+TCLFLAGS= --disable-corefoundation
JOBS = 4
diff --git a/make.linux b/make.linux
index 00ba4e7..5ebb47a 100644
--- a/make.linux
+++ b/make.linux
@@ -4,14 +4,15 @@ ARCH = linux
X11INCLUDE=/usr/X11R6/include
X11LIB = /usr/X11R6/lib
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ =
+# we need this to find M_PI and isfinite() in math.h
+ZZ = -m32 -D_GNU_SOURCE
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
#CXX = g++
diff --git a/make.linux64 b/make.linux64
index 7438e11..bd2fb02 100644
--- a/make.linux64
+++ b/make.linux64
@@ -4,14 +4,14 @@ ARCH = linux64
X11INCLUDE=/usr/include/X11
X11LIB = /usr/lib64
-XX = -O2
+XX =
YY = -g -fno-inline
ZZ = -m64 -Wl,--hash-style=both
AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D__M64
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
+OPTS = ${XX} ${ZZ}
+#OPTS = ${YY} ${ZZ}
NOPTS = ${YY} ${ZZ}
CXX = g++
@@ -23,5 +23,7 @@ CCOPT = ${OPTS} ${AA}
CCNOPT = ${NOPTS} ${AA}
ZCAT = zcat
+
+TCLFLAGS= --enable-64bit
JOBS = 4
diff --git a/make.darwinx86snowleopard b/make.macosxmountainlion
similarity index 68%
copy from make.darwinx86snowleopard
copy to make.macosxmountainlion
index 9c6b85e..989be00 100644
--- a/make.darwinx86snowleopard
+++ b/make.macosxmountainlion
@@ -1,15 +1,13 @@
-OS = unix
-ARCH = darwinx86snowleopard
+OS = macosx
+ARCH = macosx64x86mountainlion
-X11INCLUDE=/usr/X11/include
-X11LIB = /usr/X11/lib
-EXTTCLFLAGS=--disable-corefoundation
+X11INCLUDE=.
-XX = -O2
+XX =
YY = -gstabs+ -fno-inline
-ZZ = -arch i386
+ZZ = -m64
-AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -DMAC_OSX_TK=1 -D_MACOSX -D__M64
#OPTS = ${XX} ${ZZ}
OPTS = ${YY} ${ZZ}
@@ -28,4 +26,6 @@ ZCAT = gzcat
CODESIGN = codesign
ZIPFILE = ds9.zip
FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
+
+ASTFLAGS = star_cv_cnf_trail_type=long
JOBS = 4
diff --git a/make.macosxx86mountainlion b/make.macosxx86mountainlion
deleted file mode 100644
index 0241979..0000000
--- a/make.macosxx86mountainlion
+++ /dev/null
@@ -1,27 +0,0 @@
-OS = macosx
-ARCH = macosxx86mountainlion
-
-XX = -O2
-YY = -gstabs+ -fno-inline
-ZZ = -arch i386
-
-AA = -fPIC -DHAVE_SYS_UN_H -DHAVE_SYS_SHM_H
-
-#OPTS = ${XX} ${ZZ}
-OPTS = ${YY} ${ZZ}
-NOPTS = ${YY} ${ZZ}
-
-CXX = g++
-CXXOPT = ${OPTS} ${AA}
-CXXNOPT = ${NOPTS} ${AA}
-
-CC = gcc
-CCOPT = ${OPTS} ${AA}
-CCNOPT = ${NOPTS} ${AA}
-
-ZCAT = gzcat
-
-CODESIGN = codesign
-ZIPFILE = ds9.zip
-FILTERCOMPILER = pcc-i386-snowleopard.tar.gz
-JOBS = 1
diff --git a/make.pkgs b/make.pkgs
index bda965c..15f8014 100644
--- a/make.pkgs
+++ b/make.pkgs
@@ -1,11 +1,10 @@
#--------------------------basic
-DS9VERSION= 7.3b2
+DS9VERSION= 7.3b3
XPAVERSION= 2.1.14
#--------------------------version
-BLTVER = blt3.0
TCLVER = tcl8.6
TCLLIBVER = tcllib1.15
TCLXMLVER = Tclxml3.2
@@ -13,12 +12,13 @@ TKVER = tk8.6
TKCONVER = tkcon2.5
TKIMGVER= Img1.4
TKTABLEVER= Tktable2.10
+TLTVER = tlt3.0
+BLTVER = blt3.0
XMLRPCVER = xmlrpc0.3
#--------------------------dir
-ASTDIR= ast-7.3.1
-BLTDIR= blt3.0.1
+ASTDIR= ast-7.3.2
CHECKDNSDIR= checkdns
FUNTOOLSDIR= funtools-1.4.5
HCOMPRESSDIR = hcompress
@@ -37,6 +37,8 @@ TKDIR= tk8.6.0
TKIMGDIR= tkimg1.4
TKMPEGDIR= tkmpeg
TKTABLEDIR= tktable2.10
+TLTDIR= tlt3.0
+BLTDIR= blt3.0.1
WCSSUBSDIR= wcssubs-3.8.4
XMLRPCDIR= xmlrpc-0.3
XPADIR= xpa-2.1.14
diff --git a/make.source b/make.source
index e69de29..4fe6f1a 100644
--- a/make.source
+++ b/make.source
@@ -0,0 +1 @@
+OS = unix
diff --git a/notes.txt b/notes.txt
index 65ace36..d06074f 100644
--- a/notes.txt
+++ b/notes.txt
@@ -1,3 +1,12 @@
+1. unload context.C 144
+2. loadFinish context.C 1336
+3. loadDone frload.C 723
+4. getClip context.C 417
+5. getClip context.C 420
+6. getClip context.C 417
+7. getClip context.C 420
+
+
Ports:
porter MacOSX 10.4, MacOSX 10.5, MacOSX 10.6
duet MacOSX 10.7
@@ -50,7 +59,6 @@ Build:
HTML Comment: <!-- something -->
Future:
- MacOSX Aqua
XPAInfo
Astrometry.net
Tutorials
@@ -73,29 +81,46 @@ Future:
2D surface plot
List
- -7.3
- vfs mount point /tmp?
-
- fitsy++
- one time
- nrrd
- nrrdcompress
- hpx
- envi
- compress
- byteswap
- envi
- nrrd
- nrrdcompress
- compress
- hpx
- cubes
- share wcs
- tests
- large 64
-
- tcl/tk 8.6
+ -7.3 tlt
+ rm
+ bltBgStyle?
+ bltHash?
+ bltPool?
+ Blt_Obj?
+ bltDBuffer?
+ bltBase64?
+ TEA autoconf
+ pkgindex
+ FONT issues
+ BLT_CONFIG_NULL flags issues
+ rm WORDS_BIGENDIAN
+
+ check free(); ptr =NULL;
cygwin
+ tests/plot.sh
+ macosx
+ Fonts
+ regions?
+ zoom stack segv
+ tests/plot.sh
+
+ -7.3 macosx
+ prefs file
+ buttonbar causes window resize
+ 3d
+ prefs dialog box resize
+ space hv base
+ printing
+ bin filter
+ clip regions
+ iis
+ warppointer/querypointer
+ saveimage
+ os
+ print file(s)
+
+ -7.3 cygwin
+ segv at startup without window adjust (in panner parser)
64bit- not yet
imexam
iconify
@@ -103,9 +128,8 @@ List
display size 715x450
mods- windows global issue? tclWinFile.c,xmfbox.tcl
- mingw32
+ -7.3 windows-mingw32
tclxml
- blt
tkhtml
tkimg
xpa
@@ -114,7 +138,13 @@ List
funtools
wcssubs
- macosx
+ vfs mount point /tmp?
+ cubes
+ share wcs
+ windows slow delete?
+
+ tests
+ large 64
***
@@ -161,6 +191,7 @@ List
mosaicwfpc2
fix
+ compress.sh decam--24--15-g-4_01.fits.fz
cleanup frame.C vs frame3d.C
crop- recal LTM/V, DATASEC keywords
@@ -246,11 +277,7 @@ List
HISTORY AIPS CLEAN BMAJ= 1.2500E-02 BMIN= 1.2500E-02 BPA= 0.00
take average of 3rd axis/area=JY/BEAM
- update blt?
upgrade tkhtml?
- blt x11 only
- windows
- macosx
update install page
@@ -346,17 +373,10 @@ List
-64 bit FITS Fitsy++ fits keywords (test64bit.fits)
clean up configure mods (use autoreconf)
- blt
html
tclxml
tcllib
- macosx
- tk
- generic/tkEvent
- macosx/tkMacOSXDraw.c blt w==0
- xlib/X11/Xlib.h
-
-Bugs
[ds9|?]parser.Y allow 1e-01" and 1e-01' for vvalue
@@ -419,6 +439,7 @@ List
-Backup
+ enable regions with plot3d set
masks (per context: filename,color,mark)
problem alloc/channel/socket/var loads
mosaicimage iraf/wfpc2
@@ -476,8 +497,7 @@ List
clip overlay contours to image boundries
-Crop
-
- crop in WCS
+ crop in WCS (extract/resample)
-Examine
only works for files
@@ -926,6 +946,11 @@ Notes:
MACOSX
+install_name_tool -change /Library/Frameworks/Tk.framework/Versions/8.6/Tk @executable_path/../Frameworks//Tk.framework/Versions/8.6/Tk aa/Wish.app/Contents/MacOS/Wish
+install_name_tool -change /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl @executable_path/../Frameworks//Tcl.framework/Versions/8.6/Tcl aa/Wish.app/Contents/MacOS/Wish
+
+gcc -Os -pipe -fvisibility=hidden -prebind -headerpad_max_install_names -Wl,-search_paths_first tkAppInit.o -F/Users/joye/aa/build/tk/Deployment -framework Tk -F/Users/joye/aa/build/tcl/Deployment -framework Tcl -lpthread -framework CoreFoundation -framework Cocoa -framework Carbon -framework IOKit -lz -lpthread -framework CoreFoundation -sectcreate __TEXT __info_plist Wish-Info.plist -o wish
+
enum {
k1MonochromePixelFormat = 0x00000001, /* 1 bit indexed*/
k2IndexedPixelFormat = 0x00000002, /* 2 bit indexed*/
diff --git a/saotk/colorbar/Makefile b/saotk/colorbar/Makefile
index 576f765..a2dfe7b 100644
--- a/saotk/colorbar/Makefile
+++ b/saotk/colorbar/Makefile
@@ -4,7 +4,7 @@ CXXFLAGS = $(CXXOPT) \
-I. -I.. -I../widget -I../vector -I../list -I../util \
-I../../include -I$(X11INCLUDE)
-SS = \
+SRC = \
cbgrid.C \
colorbarbase.C \
colorbar.C \
@@ -22,16 +22,7 @@ SS = \
colormap.C \
lut.C \
sao.C \
- default.C
-
-ifeq ($(OS),unix)
-SSP = \
- colorbarpseudo.C \
- colorbarpseudocolor.C \
- colorbarpseudocolor8.C
-endif
-
-SRC = $(SS) $(SSP) \
+ default.C \
parser.C \
lex.C \
lutparser.C \
@@ -42,20 +33,13 @@ SRC = $(SS) $(SSP) \
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o parser.output lutparser.output saoparser.output
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o parser.output lutparser.output saoparser.output
parsers : parser lutparser saoparser
@@ -72,12 +56,3 @@ saoparser: FORCE
flex -Pli -osaolex.C saolex.L
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/colorbar/colorbarpseudocolor.C b/saotk/colorbar/colorbarpseudocolor.C
index 36bbeb4..bb31333 100644
--- a/saotk/colorbar/colorbarpseudocolor.C
+++ b/saotk/colorbar/colorbarpseudocolor.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include "colorbarpseudocolor.h"
#include "util.h"
diff --git a/saotk/colorbar/colorbarpseudocolor8.C b/saotk/colorbar/colorbarpseudocolor8.C
deleted file mode 100644
index d6eab02..0000000
--- a/saotk/colorbar/colorbarpseudocolor8.C
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "tcl.h"
-
-#include "colorbarpseudocolor8.h"
-#include "util.h"
-
-// Tk Canvas Widget Function Declarations
-
-int ColorbarPseudoColor8CreateProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int,
- Tcl_Obj *const []);
-
-// Colorbar Specs
-
-static Tk_CustomOption tagsOption = {
- Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
-};
-
-static Tk_ConfigSpec colorbarPseudoColor8Specs[] = {
-
- {TK_CONFIG_STRING, (char*)"-command", NULL, NULL, "colorbar",
- Tk_Offset(ColorbarBaseOptions, cmdName),
- TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-x", NULL, NULL, "1",
- Tk_Offset(ColorbarBaseOptions, x), TK_CONFIG_OPTION_SPECIFIED,
- NULL},
- {TK_CONFIG_INT, (char*)"-y", NULL, NULL, "1",
- Tk_Offset(ColorbarBaseOptions, y), TK_CONFIG_OPTION_SPECIFIED,
- NULL},
- {TK_CONFIG_INT, (char*)"-width", NULL, NULL, "512",
- Tk_Offset(ColorbarBaseOptions, width), TK_CONFIG_OPTION_SPECIFIED,
- NULL},
- {TK_CONFIG_INT, (char*)"-height", NULL, NULL, "22",
- Tk_Offset(ColorbarBaseOptions, height), TK_CONFIG_OPTION_SPECIFIED,
- NULL},
- {TK_CONFIG_ANCHOR, (char*)"-anchor", NULL, NULL, "nw",
- Tk_Offset(ColorbarBaseOptions, anchor), 0, NULL},
- {TK_CONFIG_CUSTOM, (char*)"-tags", NULL, NULL, NULL,
- 0, TK_CONFIG_NULL_OK, &tagsOption},
-
- {TK_CONFIG_STRING, (char*)"-helvetica", NULL, NULL, "helvetica",
- Tk_Offset(ColorbarBaseOptions, helvetica), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-courier", NULL, NULL, "courier",
- Tk_Offset(ColorbarBaseOptions, courier), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-times", NULL, NULL, "times",
- Tk_Offset(ColorbarBaseOptions, times), 0, NULL},
-
- {TK_CONFIG_BOOLEAN, (char*)"-orientation", NULL, NULL, "0",
- Tk_Offset(ColorbarBaseOptions, orientation), 0, NULL},
- {TK_CONFIG_INT, (char*)"-size", NULL, NULL, "20",
- Tk_Offset(ColorbarBaseOptions, size), 0, NULL},
-
- {TK_CONFIG_STRING, (char*)"-font", NULL, NULL, "helvetica",
- Tk_Offset(ColorbarBaseOptions, font), 0, NULL},
- {TK_CONFIG_INT, (char*)"-fontsize", NULL, NULL, "10",
- Tk_Offset(ColorbarBaseOptions, fontSize), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-fontweight", "fontweight", NULL, "normal",
- Tk_Offset(ColorbarBaseOptions, fontWeight), 0, NULL},
- {TK_CONFIG_SYNONYM, (char*)"-fontstyle", "fontweight", NULL, NULL, 0, 0},
- {TK_CONFIG_STRING, (char*)"-fontslant", NULL, NULL, "roman",
- Tk_Offset(ColorbarBaseOptions, fontSlant), 0, NULL},
-
- {TK_CONFIG_BOOLEAN, (char*)"-numerics", NULL, NULL, "1",
- Tk_Offset(ColorbarBaseOptions, numerics), 0, NULL},
- {TK_CONFIG_BOOLEAN, (char*)"-space", NULL, NULL, "1",
- Tk_Offset(ColorbarBaseOptions, space), 0, NULL},
- {TK_CONFIG_INT, (char*)"-ticks", NULL, NULL, "11",
- Tk_Offset(ColorbarBaseOptions, ticks), 0, NULL},
-
- {TK_CONFIG_INT, (char*)"-min", NULL, NULL, "80",
- Tk_Offset(ColorbarBaseOptions, minColors), 0, NULL},
- {TK_CONFIG_INT, (char*)"-max", NULL, NULL, "200",
- Tk_Offset(ColorbarBaseOptions, maxColors), 0, NULL},
- {TK_CONFIG_BOOLEAN, (char*)"-private", NULL, NULL, "false",
- Tk_Offset(ColorbarBaseOptions, privateCmap), 0, NULL},
- {TK_CONFIG_INT, (char*)"-privatecolors", NULL, NULL, "128",
- Tk_Offset(ColorbarBaseOptions, privateColors), 0, NULL},
-
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL},
-};
-
-// Tk Static Structure
-
-static Tk_ItemType colorbarPseudoColor8Type = {
- (char*)"colorbarpseudocolor8", // name
- sizeof(ColorbarBaseOptions), // size
- ColorbarPseudoColor8CreateProc, // configProc
- colorbarPseudoColor8Specs, // configSpecs
- WidgetConfigProc, // configProc
- WidgetCoordProc, // coordProc
- WidgetDeleteProc, // deleteProc
- WidgetDisplayProc, // displayProc
- 0, // alwaysRedraw
- WidgetPointProc, // pointProc
- WidgetAreaProc, // areaProc
- WidgetPostscriptProc, // postscriptProc
- WidgetScaleProc, // scaleProc
- WidgetTranslateProc, // translateProc
- (Tk_ItemIndexProc*)NULL, // indexProc
- (Tk_ItemCursorProc*)NULL, // icursorProc
- (Tk_ItemSelectionProc*)NULL, // selectionProc
- (Tk_ItemInsertProc*)NULL, // insertProc
- (Tk_ItemDCharsProc*)NULL, // dCharsProc
- (Tk_ItemType*)NULL // nextPtr
-};
-
-// Non-Member Functions
-
-int ColorbarPseudoColor8_Init(Tcl_Interp* interp)
-{
- Tk_CreateItemType(&colorbarPseudoColor8Type);
- return TCL_OK;
-}
-
-int ColorbarPseudoColor8CreateProc(Tcl_Interp* interp, Tk_Canvas canvas,
- Tk_Item* item, int argc,
- Tcl_Obj *const argv[])
-{
- ColorbarPseudoColor8* colorbar =
- new ColorbarPseudoColor8(interp, canvas, item);
-
- // and set default configuration
- if (colorbar->configure(argc, (const char**)argv, 0) != TCL_OK) {
- delete colorbar;
- Tcl_AppendResult(interp, " error occured while creating colorbar.", NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-// ColorbarPseudoColor8
-
-ColorbarPseudoColor8::ColorbarPseudoColor8(Tcl_Interp* i, Tk_Canvas c,
- Tk_Item* item)
- : ColorbarBase(i,c,item), ColorbarPseudoColor(i,c,item)
-{
- configSpecs = colorbarPseudoColor8Specs; // colorbar configure options
-
- loadDefaultCMaps();
-}
-
-// UpdatePixmap. This function is responsable for creating a valid
-// pixmap the size of the current Colorbar
-
-void ColorbarPseudoColor8::ximageToPixmap()
-{
- if (!((ColorbarBaseOptions*)options)->orientation) {
- ximageToPixmapHorz();
- XPutImage(display, pixmap, gc, xmap, 0, 0, 1, 1,
- options->width-2, ((ColorbarBaseOptions*)options)->size-2);
- }
- else {
- ximageToPixmapVert();
- XPutImage(display, pixmap, gc, xmap, 0, 0, 1, 1,
- ((ColorbarBaseOptions*)options)->size-2, options->height-2);
- }
-}
-
-void ColorbarPseudoColor8::ximageToPixmapHorz()
-{
- int width = options->width-2;
- int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
-
- // Fill in colorbar data
- // --Calculate first row
- for (int ii=0; ii<width; ii++)
- data[ii] = (char)colorIndex[ii*colorCount/width];
-
- // --and duplicate for remaining rows
- for (int jj=1; jj<height; jj++)
- memcpy(data+(jj*xmap->bytes_per_line), data, xmap->bytes_per_line);
-}
-
-void ColorbarPseudoColor8::ximageToPixmapVert()
-{
- int width = ((ColorbarBaseOptions*)options)->size-2;
- int height = options->height-2;
- char* data = XImageData(xmap);
-
- for (int jj=height-1; jj>=0; jj--, data+=xmap->bytes_per_line) {
- char a = (char)colorIndex[jj*colorCount/height];
- for (int ii=0; ii<width; ii++)
- data[ii] = a;
- }
-}
diff --git a/saotk/colorbar/colorbarrgbtruecolor.C b/saotk/colorbar/colorbarrgbtruecolor.C
index 26cce50..f77de70 100644
--- a/saotk/colorbar/colorbarrgbtruecolor.C
+++ b/saotk/colorbar/colorbarrgbtruecolor.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include "colorbarrgbtruecolor.h"
#include "util.h"
diff --git a/saotk/colorbar/colorbarrgbtruecolor16.C b/saotk/colorbar/colorbarrgbtruecolor16.C
index e34527f..426f415 100644
--- a/saotk/colorbar/colorbarrgbtruecolor16.C
+++ b/saotk/colorbar/colorbarrgbtruecolor16.C
@@ -137,7 +137,7 @@ void ColorbarRGBTrueColor16::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
// if we have cross platforms, we need to byte swap
unsigned char row[xmap->bytes_per_line];
@@ -216,7 +216,7 @@ void ColorbarRGBTrueColor16::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
// if we have cross platforms, we need to byte swap
if ((!xmap->byte_order && lsb()) || (xmap->byte_order && !lsb())) {
diff --git a/saotk/colorbar/colorbarrgbtruecolor24.C b/saotk/colorbar/colorbarrgbtruecolor24.C
index 8d75756..0cf05b5 100644
--- a/saotk/colorbar/colorbarrgbtruecolor24.C
+++ b/saotk/colorbar/colorbarrgbtruecolor24.C
@@ -135,7 +135,7 @@ void ColorbarRGBTrueColor24::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
switch (xmap->bits_per_pixel) {
case 32:
@@ -154,7 +154,7 @@ void ColorbarRGBTrueColor24::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
switch (xmap->bits_per_pixel) {
case 32:
@@ -334,10 +334,14 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
// if we have cross platforms, we need to byte swap
unsigned char row[xmap->bytes_per_line];
if ((!xmap->byte_order && lsb()) || (xmap->byte_order && !lsb())) {
- //red
+
+ // red
for (int ii=0; ii<width; ii++) {
unsigned int r = colorCells[(int)(double(ii)/width*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
memcpy(row+ii*4, &a, 4);
}
@@ -348,6 +352,9 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
for (int ii=0; ii<width; ii++) {
unsigned int g = colorCells[(int)(double(ii)/width*colorCount)*3+1];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= g << gs_;
memcpy(row+ii*4, &a, 4);
}
@@ -358,6 +365,9 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
for (int ii=0; ii<width; ii++) {
unsigned int b = colorCells[(int)(double(ii)/width*colorCount)*3+2];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= b << bs_;
memcpy(row+ii*4, &a, 4);
}
@@ -370,6 +380,9 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
for (int i=0; i<width; i++) {
unsigned int r = colorCells[(int)(double(i)/width*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
unsigned char* rr = (unsigned char*)(&a);
*(row+i*4) = *(rr+3);
@@ -384,6 +397,9 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
for (int i=0; i<width; i++) {
unsigned int g = colorCells[(int)(double(i)/width*colorCount)*3+1];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= g << gs_;
unsigned char* rr = (unsigned char*)(&a);
*(row+i*4) = *(rr+3);
@@ -398,6 +414,9 @@ void ColorbarRGBTrueColor24::updateColors32Horz(int width, int height,
for (int i=0; i<width; i++) {
unsigned int b = colorCells[(int)(double(i)/width*colorCount)*3+2];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= b << bs_;
unsigned char* rr = (unsigned char*)(&a);
*(row+i*4) = *(rr+3);
@@ -421,6 +440,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int r = colorCells[(int)(double(jj)/height*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
for (int ii=0; ii<(int)(width/3.); ii++)
memcpy(data+ii*4, &a, 4);
@@ -430,6 +452,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int g = colorCells[(int)(double(jj)/height*colorCount)*3+1];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= g << gs_;
for (int ii=(int)(width/3.); ii<(int)(width*2/3.); ii++)
memcpy(data+ii*4, &a, 4);
@@ -439,6 +464,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int b = colorCells[(int)(double(jj)/height*colorCount)*3+2];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= b << bs_;
for (int ii=(int)(width*2/3.); ii<width; ii++)
memcpy(data+ii*4, &a, 4);
@@ -452,6 +480,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int r = colorCells[(int)(double(jj)/height*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
unsigned char* rr = (unsigned char*)(&a);
for (int ii=0; ii<(int)(width/3.); ii++) {
@@ -466,6 +497,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int g = colorCells[(int)(double(jj)/height*colorCount)*3+1];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= g << gs_;
unsigned char* rr = (unsigned char*)(&a);
for (int ii=(int)(width/3.); ii<(int)(width*2/3.); ii++) {
@@ -480,6 +514,9 @@ void ColorbarRGBTrueColor24::updateColors32Vert(int width, int height,
{
unsigned int b = colorCells[(int)(double(jj)/height*colorCount)*3+2];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= b << bs_;
unsigned char* rr = (unsigned char*)(&a);
for (int ii=(int)(width*2/3.); ii<width; ii++) {
diff --git a/saotk/colorbar/colorbarrgbtruecolor8.C b/saotk/colorbar/colorbarrgbtruecolor8.C
index 70a97db..92b780e 100644
--- a/saotk/colorbar/colorbarrgbtruecolor8.C
+++ b/saotk/colorbar/colorbarrgbtruecolor8.C
@@ -135,7 +135,7 @@ void ColorbarRGBTrueColor8::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
unsigned char row[xmap->bytes_per_line];
@@ -168,7 +168,7 @@ void ColorbarRGBTrueColor8::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
for (int jj=height-1; jj>=0; jj--, data+=xmap->bytes_per_line) {
diff --git a/saotk/colorbar/colorbartrue.C b/saotk/colorbar/colorbartrue.C
index cda4271..5eb56a5 100644
--- a/saotk/colorbar/colorbartrue.C
+++ b/saotk/colorbar/colorbartrue.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include "colorbartrue.h"
#include "util.h"
diff --git a/saotk/colorbar/colorbartruecolor.C b/saotk/colorbar/colorbartruecolor.C
index 8424598..50c38ed 100644
--- a/saotk/colorbar/colorbartruecolor.C
+++ b/saotk/colorbar/colorbartruecolor.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include "colorbartruecolor.h"
#include "util.h"
diff --git a/saotk/colorbar/colorbartruecolor16.C b/saotk/colorbar/colorbartruecolor16.C
index fd086d2..2cf02ec 100644
--- a/saotk/colorbar/colorbartruecolor16.C
+++ b/saotk/colorbar/colorbartruecolor16.C
@@ -136,7 +136,7 @@ void ColorbarTrueColor16::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
// if we have cross platforms, we need to byte swap
if ((!xmap->byte_order && lsb()) || (xmap->byte_order && !lsb())) {
@@ -177,7 +177,7 @@ void ColorbarTrueColor16::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
// if we have cross platforms, we need to byte swap
if ((!xmap->byte_order && lsb()) || (xmap->byte_order && !lsb())) {
diff --git a/saotk/colorbar/colorbartruecolor24.C b/saotk/colorbar/colorbartruecolor24.C
index e8be2dd..b11d504 100644
--- a/saotk/colorbar/colorbartruecolor24.C
+++ b/saotk/colorbar/colorbartruecolor24.C
@@ -135,7 +135,7 @@ void ColorbarTrueColor24::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
switch (xmap->bits_per_pixel) {
case 32:
@@ -154,7 +154,7 @@ void ColorbarTrueColor24::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
switch (xmap->bits_per_pixel) {
case 32:
@@ -253,6 +253,9 @@ void ColorbarTrueColor24::updateColors32Horz(int width, int height, char* data)
unsigned int g = colorCells[(int)(double(ii)/width*colorCount)*3+1];
unsigned int b = colorCells[(int)(double(ii)/width*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
@@ -266,6 +269,9 @@ void ColorbarTrueColor24::updateColors32Horz(int width, int height, char* data)
unsigned int g = colorCells[(int)(double(ii)/width*colorCount)*3+1];
unsigned int b = colorCells[(int)(double(ii)/width*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
@@ -292,6 +298,9 @@ void ColorbarTrueColor24::updateColors32Vert(int width, int height, char* data)
unsigned int g = colorCells[(int)(double(jj)/height*colorCount)*3+1];
unsigned int b = colorCells[(int)(double(jj)/height*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
@@ -306,6 +315,9 @@ void ColorbarTrueColor24::updateColors32Vert(int width, int height, char* data)
unsigned int g = colorCells[(int)(double(jj)/height*colorCount)*3+1];
unsigned int b = colorCells[(int)(double(jj)/height*colorCount)*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
diff --git a/saotk/colorbar/colorbartruecolor8.C b/saotk/colorbar/colorbartruecolor8.C
index 6f39eef..ef42f97 100644
--- a/saotk/colorbar/colorbartruecolor8.C
+++ b/saotk/colorbar/colorbartruecolor8.C
@@ -137,7 +137,7 @@ void ColorbarTrueColor8::updateColorsHorz()
{
int width = options->width-2;
int height = ((ColorbarBaseOptions*)options)->size-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
for (int ii=0; ii<width; ii++)
data[ii] =
@@ -154,7 +154,7 @@ void ColorbarTrueColor8::updateColorsVert()
{
int width = ((ColorbarBaseOptions*)options)->size-2;
int height = options->height-2;
- char* data = XImageData(xmap);
+ char* data = xmap->data;
for (int jj=height-1; jj>=0; jj--, data+=xmap->bytes_per_line) {
char a =
diff --git a/saotk/colorbar/colortag.h b/saotk/colorbar/colortag.h
index 99d3d8b..24c6b72 100644
--- a/saotk/colorbar/colortag.h
+++ b/saotk/colorbar/colortag.h
@@ -15,8 +15,8 @@
#include <iomanip>
using namespace std;
-#include <tcl.h>
-#include <tk.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
class Colorbar;
diff --git a/saotk/fitsy++/Makefile b/saotk/fitsy++/Makefile
index 5e37b21..94767d8 100644
--- a/saotk/fitsy++/Makefile
+++ b/saotk/fitsy++/Makefile
@@ -57,20 +57,13 @@ SRC = $(SS) \
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o parser.output nrrdparser.output enviparser.output
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o parser.output nrrdparser.output enviparser.output
parsers : parser nrrdparser enviparser
@@ -92,12 +85,3 @@ shmload : shmload.C
cp $@ ../../bin/.
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SS:.C=.d)
-endif
diff --git a/saotk/fitsy++/alloc.C b/saotk/fitsy++/alloc.C
index 3b124b6..82ff2cd 100644
--- a/saotk/fitsy++/alloc.C
+++ b/saotk/fitsy++/alloc.C
@@ -2,6 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <stdio.h>
#include "alloc.h"
FitsAlloc::FitsAlloc(const char* fn)
diff --git a/saotk/fitsy++/analysis.C b/saotk/fitsy++/analysis.C
index 5754d9f..ffd2b5f 100644
--- a/saotk/fitsy++/analysis.C
+++ b/saotk/fitsy++/analysis.C
@@ -14,7 +14,6 @@ FitsAnalysis::FitsAnalysis(FitsFile* src)
ext_ = src->ext();
inherit_ = src->inherit();
- byteswap_ = 0;
// change bitpix to double
head_->setInteger("BITPIX", -64, "");
@@ -44,7 +43,8 @@ FitsAnalysis::FitsAnalysis(FitsFile* src)
memset(data_, 0, size*sizeof(double));
// made it this far, must be valid
- orgFits_ = 0;
+ byteswap_ = 0;
+ endian_ = lsb() ? LITTLE : BIG;
valid_ = 1;
}
diff --git a/saotk/fitsy++/channel.C b/saotk/fitsy++/channel.C
index 44f1eb7..8b528be 100644
--- a/saotk/fitsy++/channel.C
+++ b/saotk/fitsy++/channel.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tcl.h>
+
#include "channel.h"
FitsChannel::FitsChannel(Tcl_Interp* interp, const char* ch, const char* ext)
diff --git a/saotk/fitsy++/compress.C b/saotk/fitsy++/compress.C
index e70266a..85c6283 100644
--- a/saotk/fitsy++/compress.C
+++ b/saotk/fitsy++/compress.C
@@ -729,7 +729,7 @@ template class FitsCompressm<long long>;
template class FitsCompressm<float>;
template class FitsCompressm<double>;
-FitsCompressNext::FitsCompressNext(FitsFile* p)
+FitsPostNext::FitsPostNext(FitsFile* p)
{
FitsCompress* prev = (FitsCompress*)p;
@@ -747,15 +747,8 @@ FitsCompressNext::FitsCompressNext(FitsFile* p)
ext_ = prev->ext();
inherit_ = head_->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
return;
}
diff --git a/saotk/fitsy++/compress.h b/saotk/fitsy++/compress.h
index d05430d..11464c0 100644
--- a/saotk/fitsy++/compress.h
+++ b/saotk/fitsy++/compress.h
@@ -81,9 +81,9 @@ class FitsCompressm : public FitsCompress {
FitsCompressm(FitsFile*);
};
-class FitsCompressNext : public FitsFile {
+class FitsPostNext : public FitsFile {
public:
- FitsCompressNext(FitsFile* prev);
+ FitsPostNext(FitsFile* prev);
};
#endif
diff --git a/saotk/fitsy++/envi.C b/saotk/fitsy++/envi.C
index a17cf85..c733afc 100644
--- a/saotk/fitsy++/envi.C
+++ b/saotk/fitsy++/envi.C
@@ -5,17 +5,23 @@
#include "envi.h"
#include "head.h"
-FitsENVI::FitsENVI(FitsFile* fits) : FitsFile(fits)
+FitsENVI::FitsENVI(FitsFile* fits)
{
- pSize_ = (size_t)pWidth_*pHeight_*pDepth_;
- pSkip_ = 0;
- pArch_ = fits->pArch();
+ byteswap_ = fits->byteswap();
+ endian_ = fits->endian();
+
+ pBitpix_ = fits->pBitpix();
+ pWidth_ = fits->pWidth();
+ pHeight_ = fits->pHeight();
+ pDepth_ = fits->pDepth();
pEncoding_ = FitsFile::BSQ;
pCRPIX3_ = fits->pCRPIX3();
pCRVAL3_ = fits->pCRVAL3();
pCDELT3_ = fits->pCDELT3();
+
+ size_ = (size_t)pWidth_*pHeight_*pDepth_;
}
FitsENVI::~FitsENVI()
@@ -62,198 +68,18 @@ int FitsENVI::initHeader(FitsFile* fits)
return 1;
}
-template<class T> FitsENVIm<T>::FitsENVIm(FitsFile* fits)
- : FitsENVI(fits)
-{
- // cerr << "FitsENVIm<T>(FitsFile* fits)" << endl;
-}
-
-template<class T> void FitsENVIm<T>::swapBytes(FitsFile::ArchType arch)
-{
- switch (arch) {
- case FitsFile::NATIVE:
- break;
- case FitsFile::BIG:
- if (!byteswap_) {
- T* dest = (T*)data_;
- for (int i=0; i<pSize_; i++)
- dest[i] = swap(dest+i);
- }
- break;
- case FitsFile::LITTLE:
- if (byteswap_) {
- T* dest = (T*)data_;
- for (int i=0; i<pSize_; i++)
- dest[i] = swap(dest+i);
- }
- break;
- }
-}
-
-template <> unsigned char FitsENVIm<unsigned char>::swap(unsigned char* ptr)
-{
- return *ptr;
-}
-
-template <> short FitsENVIm<short>::swap(short* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[2];
- short s;
- } u;
-
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.s;
-}
-
-template <> unsigned short FitsENVIm<unsigned short>::swap(unsigned short* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[2];
- unsigned short s;
- } u;
-
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.s;
-}
-
-template <> int FitsENVIm<int>::swap(int* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[4];
- int i;
- } u;
-
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.i;
-}
-
-template <> long long FitsENVIm<long long>::swap(long long* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[8];
- long long i;
- } u;
-
- u.c[7] = *p++;
- u.c[6] = *p++;
- u.c[5] = *p++;
- u.c[4] = *p++;
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.i;
-}
-
-template <> float FitsENVIm<float>::swap(float* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[4];
- float f;
- } u;
-
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.f;
-}
-
-template <> double FitsENVIm<double>::swap(double* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[8];
- double d;
- } u;
-
- u.c[7] = *p++;
- u.c[6] = *p++;
- u.c[5] = *p++;
- u.c[4] = *p++;
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.d;
-}
-
-template class FitsENVIm<unsigned char>;
-template class FitsENVIm<short>;
-template class FitsENVIm<unsigned short>;
-template class FitsENVIm<int>;
-template class FitsENVIm<long long>;
-template class FitsENVIm<float>;
-template class FitsENVIm<double>;
-
-FitsENVINext::FitsENVINext(FitsFile* p)
-{
- FitsENVI* prev = (FitsENVI*)p;
-
- primary_ = prev->primary();
- managePrimary_ = 0;
-
- head_ = prev->head();
- manageHead_ = 0;
-
- FitsImageHDU* hdu = (FitsImageHDU*)head_->hdu();
- data_ = (char*)prev->data() + hdu->imgbytes();
- dataSize_ = 0;
- dataSkip_ = 0;
-
- ext_ = prev->ext();
- inherit_ = prev->inherit();
- byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
- valid_ = 1;
-
- pBitpix_ = prev->pBitpix();
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
- pEncoding_ = prev->pEncoding();
-
- pCRPIX3_ = prev->pCRPIX3();
- pCRVAL3_ = prev->pCRVAL3();
- pCDELT3_ = prev->pCDELT3();
-
- return;
-}
-
template <class T> FitsENVIBIPm<T>::FitsENVIBIPm(FitsFile* fits)
: FitsENVI(fits)
{
- // cerr << "FitsENVIBIPm(FitsFile* fits)" << endl;
-
if (!initHeader(fits))
return;
- T* dest = new T[pSize_];
+ T* dest = new T[size_];
if (!dest) {
internalError("Fitsy++ envi unable to allocate memory");
return;
}
- memset(dest, 0, pSize_*sizeof(T));
+ memset(dest, 0, size_*sizeof(T));
T* ptr = (T*)fits->data();
for (int jj=0; jj<pHeight_; jj++)
@@ -263,7 +89,7 @@ template <class T> FitsENVIBIPm<T>::FitsENVIBIPm(FitsFile* fits)
data_ = dest;
- dataSize_ = pSize_;
+ dataSize_ = size_;
dataSkip_ = 0;
// all done
@@ -281,17 +107,15 @@ template class FitsENVIBIPm<double>;
template <class T> FitsENVIBILm<T>::FitsENVIBILm(FitsFile* fits)
: FitsENVI(fits)
{
- // cerr << "FitsENVIBILm(FitsFile* fits)" << endl;
-
if (!initHeader(fits))
return;
- T* dest = new T[pSize_];
+ T* dest = new T[size_];
if (!dest) {
internalError("Fitsy++ envi unable to allocate memory");
return;
}
- memset(dest, 0, pSize_*sizeof(T));
+ memset(dest, 0, size_*sizeof(T));
T* ptr = (T*)fits->data();
for (int jj=0; jj<pHeight_; jj++)
@@ -301,7 +125,7 @@ template <class T> FitsENVIBILm<T>::FitsENVIBILm(FitsFile* fits)
data_ = dest;
- dataSize_ = pSize_;
+ dataSize_ = size_;
dataSkip_ = 0;
// all done
diff --git a/saotk/fitsy++/envi.h b/saotk/fitsy++/envi.h
index 87d13b8..2739296 100644
--- a/saotk/fitsy++/envi.h
+++ b/saotk/fitsy++/envi.h
@@ -9,6 +9,9 @@
class FitsENVI : public FitsFile {
protected:
+ size_t size_;
+
+ protected:
int initHeader(FitsFile*);
public:
@@ -17,23 +20,6 @@ class FitsENVI : public FitsFile {
};
template<class T>
-class FitsENVIm : public FitsENVI {
- private:
- void swapBytes(FitsFile::ArchType);
-
- protected:
- T swap(T* ptr);
-
- public:
- FitsENVIm(FitsFile*);
-};
-
-class FitsENVINext : public FitsFile {
-public:
- FitsENVINext(FitsFile* prev);
-};
-
-template<class T>
class FitsENVIBILm : public FitsENVI {
public:
FitsENVIBILm(FitsFile*);
diff --git a/saotk/fitsy++/envilex.C b/saotk/fitsy++/envilex.C
index 1d858e4..d97f5ef 100644
--- a/saotk/fitsy++/envilex.C
+++ b/saotk/fitsy++/envilex.C
@@ -324,8 +324,8 @@ int yyFlexLexer::yywrap() { return 1; }
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 69
-#define YY_END_OF_BUFFER 70
+#define YY_NUM_RULES 72
+#define YY_END_OF_BUFFER 73
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -333,38 +333,39 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[273] =
+static yyconst flex_int16_t yy_accept[282] =
{ 0,
- 0, 0, 2, 2, 0, 0, 70, 68, 65, 67,
- 68, 68, 68, 61, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 3, 2, 1, 60, 58, 59,
- 60, 57, 56, 60, 53, 56, 4, 65, 66, 0,
- 61, 63, 62, 61, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 6, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 2, 58, 0, 53, 56,
-
- 53, 55, 54, 56, 0, 0, 0, 62, 64, 64,
- 11, 12, 13, 14, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 31, 64, 64, 7, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 0, 0, 0, 56, 54, 62, 0, 63, 64,
- 9, 15, 17, 64, 64, 64, 16, 64, 22, 64,
- 23, 24, 64, 64, 26, 64, 64, 64, 64, 64,
- 64, 64, 64, 38, 64, 64, 64, 64, 64, 64,
- 45, 64, 64, 48, 64, 64, 64, 54, 0, 55,
-
- 64, 10, 5, 64, 64, 64, 21, 64, 64, 64,
- 29, 30, 32, 33, 64, 36, 37, 64, 40, 64,
- 64, 43, 64, 64, 64, 49, 50, 64, 64, 64,
- 64, 20, 25, 27, 64, 34, 64, 64, 64, 44,
- 64, 47, 51, 64, 8, 18, 64, 64, 35, 64,
- 64, 42, 46, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 28, 39, 64, 52, 19,
- 41, 0
+ 0, 0, 2, 2, 0, 0, 73, 71, 68, 70,
+ 71, 71, 71, 64, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 3, 2, 1, 63, 61, 62,
+ 63, 60, 59, 63, 56, 59, 4, 68, 69, 0,
+ 64, 66, 65, 64, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 6, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 2, 61, 0, 56, 59,
+
+ 56, 58, 57, 59, 0, 0, 0, 65, 67, 67,
+ 11, 12, 13, 14, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 32, 67, 67, 7, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 0, 0, 0, 59, 57, 65, 0, 66,
+ 67, 9, 15, 17, 67, 67, 67, 16, 67, 22,
+ 67, 23, 24, 67, 67, 26, 67, 67, 67, 67,
+ 67, 67, 67, 67, 67, 40, 67, 67, 67, 67,
+ 67, 67, 67, 48, 67, 67, 51, 67, 67, 67,
+
+ 57, 0, 58, 67, 10, 5, 67, 67, 67, 21,
+ 67, 67, 67, 67, 30, 31, 33, 34, 67, 37,
+ 38, 67, 42, 67, 67, 45, 67, 67, 67, 67,
+ 52, 53, 67, 67, 67, 67, 20, 25, 27, 67,
+ 29, 35, 39, 67, 67, 67, 67, 47, 67, 50,
+ 54, 67, 8, 18, 67, 67, 36, 67, 67, 44,
+ 46, 49, 67, 67, 67, 67, 67, 67, 67, 67,
+ 67, 67, 67, 67, 28, 41, 67, 55, 19, 43,
+ 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -410,75 +411,77 @@ static yyconst flex_int32_t yy_meta[63] =
1, 1
} ;
-static yyconst flex_int16_t yy_base[278] =
+static yyconst flex_int16_t yy_base[287] =
{ 0,
- 0, 0, 779, 778, 62, 124, 780, 783, 777, 783,
- 771, 64, 753, 66, 78, 179, 753, 68, 69, 127,
+ 0, 0, 806, 805, 62, 124, 807, 810, 800, 810,
+ 788, 64, 781, 66, 78, 179, 781, 68, 69, 127,
71, 75, 128, 76, 77, 80, 150, 148, 132, 231,
- 144, 91, 83, 102, 783, 0, 783, 783, 758, 783,
- 88, 783, 92, 749, 141, 749, 783, 753, 783, 745,
- 187, 134, 190, 197, 745, 212, 153, 202, 201, 227,
+ 144, 91, 83, 102, 810, 0, 810, 810, 786, 810,
+ 88, 810, 92, 778, 141, 778, 810, 783, 810, 775,
+ 187, 134, 190, 197, 775, 212, 153, 202, 201, 227,
200, 204, 226, 246, 228, 145, 210, 232, 236, 254,
- 255, 258, 274, 270, 282, 286, 278, 280, 744, 284,
- 296, 288, 300, 294, 305, 297, 323, 303, 306, 95,
- 314, 322, 327, 331, 330, 0, 749, 739, 348, 738,
-
- 355, 339, 341, 375, 369, 380, 735, 220, 365, 352,
- 734, 732, 730, 728, 382, 389, 385, 390, 393, 386,
- 394, 395, 398, 399, 404, 400, 408, 410, 428, 429,
- 425, 726, 430, 433, 436, 442, 447, 443, 457, 450,
- 454, 403, 459, 455, 463, 470, 473, 477, 478, 482,
- 485, 504, 509, 723, 487, 512, 706, 704, 699, 514,
- 498, 678, 668, 507, 522, 519, 667, 480, 626, 520,
- 624, 610, 525, 527, 602, 528, 530, 532, 534, 535,
- 533, 537, 523, 548, 554, 558, 562, 566, 567, 577,
- 545, 549, 582, 493, 583, 585, 574, 489, 461, 451,
-
- 589, 421, 416, 592, 596, 540, 411, 600, 601, 598,
- 406, 402, 367, 362, 608, 359, 350, 609, 332, 616,
- 615, 328, 622, 627, 625, 308, 635, 637, 642, 638,
- 634, 302, 268, 262, 650, 640, 652, 658, 661, 256,
- 653, 238, 216, 649, 206, 174, 665, 675, 172, 683,
- 690, 156, 152, 663, 691, 672, 694, 699, 687, 696,
- 709, 702, 721, 713, 716, 133, 110, 723, 103, 97,
- 94, 783, 764, 768, 94, 772, 774
+ 255, 258, 274, 270, 282, 286, 278, 280, 772, 297,
+ 289, 288, 296, 300, 311, 294, 303, 306, 316, 95,
+ 327, 325, 322, 323, 330, 0, 776, 768, 349, 767,
+
+ 351, 353, 359, 375, 365, 383, 765, 220, 369, 387,
+ 765, 764, 763, 761, 371, 393, 379, 394, 386, 389,
+ 398, 400, 397, 409, 402, 407, 404, 408, 427, 405,
+ 428, 414, 760, 431, 429, 437, 446, 456, 443, 439,
+ 458, 467, 451, 470, 453, 463, 465, 474, 475, 479,
+ 477, 484, 505, 512, 757, 334, 514, 756, 751, 750,
+ 494, 501, 750, 746, 518, 517, 519, 739, 520, 725,
+ 523, 687, 684, 527, 528, 636, 530, 532, 531, 535,
+ 537, 540, 562, 548, 544, 629, 565, 569, 577, 573,
+ 584, 580, 550, 570, 587, 593, 558, 598, 596, 600,
+
+ 544, 542, 541, 606, 541, 534, 604, 605, 588, 503,
+ 603, 621, 610, 619, 491, 486, 454, 440, 624, 410,
+ 626, 630, 370, 631, 644, 363, 649, 654, 652, 657,
+ 356, 658, 659, 662, 651, 663, 347, 345, 341, 669,
+ 338, 666, 268, 667, 674, 679, 685, 262, 683, 256,
+ 238, 693, 216, 206, 689, 712, 174, 690, 715, 172,
+ 156, 152, 719, 696, 589, 707, 716, 709, 721, 722,
+ 734, 738, 736, 744, 133, 110, 741, 103, 97, 94,
+ 810, 792, 796, 94, 800, 802
} ;
-static yyconst flex_int16_t yy_def[278] =
+static yyconst flex_int16_t yy_def[287] =
{ 0,
- 272, 1, 273, 273, 274, 274, 272, 272, 272, 272,
- 272, 272, 272, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 272, 276, 272, 272, 272, 272,
- 272, 272, 277, 272, 277, 277, 272, 272, 272, 272,
- 272, 272, 272, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 276, 272, 272, 272, 277,
-
- 277, 272, 272, 277, 272, 272, 272, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 272, 272, 272, 277, 277, 272, 272, 272, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 272, 272, 272,
-
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 0, 272, 272, 272, 272, 272
+ 281, 1, 282, 282, 283, 283, 281, 281, 281, 281,
+ 281, 281, 281, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 281, 285, 281, 281, 281, 281,
+ 281, 281, 286, 281, 286, 286, 281, 281, 281, 281,
+ 281, 281, 281, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 285, 281, 281, 281, 286,
+
+ 286, 281, 281, 286, 281, 281, 281, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 281, 281, 281, 286, 286, 281, 281, 281,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+
+ 281, 281, 281, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 284, 284, 284, 284, 284, 284, 284, 284, 284, 284,
+ 0, 281, 281, 281, 281, 281
} ;
-static yyconst flex_int16_t yy_nxt[846] =
+static yyconst flex_int16_t yy_nxt[873] =
{ 0,
8, 9, 10, 11, 12, 8, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 17, 17,
@@ -487,95 +490,98 @@ static yyconst flex_int16_t yy_nxt[846] =
20, 21, 22, 23, 17, 24, 25, 26, 27, 28,
17, 29, 30, 31, 32, 33, 34, 17, 17, 17,
35, 8, 38, 39, 40, 38, 41, 42, 43, 44,
- 45, 50, 51, 53, 54, 272, 272, 63, 272, 56,
- 70, 64, 272, 272, 272, 272, 75, 272, 71, 77,
- 272, 65, 94, 74, 76, 98, 99, 55, 272, 98,
-
- 101, 272, 272, 63, 272, 56, 70, 64, 57, 272,
- 272, 95, 75, 93, 71, 77, 65, 272, 94, 74,
- 76, 146, 38, 47, 38, 39, 40, 38, 41, 42,
- 43, 44, 45, 57, 272, 272, 66, 95, 93, 272,
- 272, 84, 52, 72, 67, 85, 146, 106, 103, 101,
- 73, 272, 272, 68, 104, 272, 121, 272, 69, 272,
- 272, 91, 66, 272, 78, 81, 109, 84, 82, 72,
- 67, 85, 79, 106, 83, 73, 80, 92, 68, 272,
- 104, 272, 121, 69, 38, 47, 272, 91, 58, 59,
+ 45, 50, 51, 53, 54, 281, 281, 63, 281, 56,
+ 70, 64, 281, 281, 281, 281, 75, 281, 71, 77,
+ 281, 65, 94, 74, 76, 98, 99, 55, 281, 98,
+
+ 101, 281, 281, 63, 281, 56, 70, 64, 57, 281,
+ 281, 95, 75, 93, 71, 77, 65, 281, 94, 74,
+ 76, 147, 38, 47, 38, 39, 40, 38, 41, 42,
+ 43, 44, 45, 57, 281, 281, 66, 95, 93, 281,
+ 281, 84, 52, 72, 67, 85, 147, 106, 103, 101,
+ 73, 281, 281, 68, 104, 281, 121, 281, 69, 281,
+ 281, 91, 66, 281, 78, 81, 109, 84, 82, 72,
+ 67, 85, 79, 106, 83, 73, 80, 92, 68, 281,
+ 104, 281, 121, 69, 38, 47, 281, 91, 58, 59,
78, 81, 109, 82, 53, 51, 60, 79, 52, 83,
- 105, 80, 92, 105, 53, 54, 61, 272, 272, 272,
- 56, 272, 62, 272, 58, 59, 107, 272, 107, 272,
- 108, 111, 60, 272, 110, 114, 105, 272, 108, 105,
- 122, 61, 115, 272, 272, 272, 56, 62, 272, 272,
- 86, 123, 87, 272, 88, 272, 111, 112, 89, 110,
- 114, 113, 124, 272, 116, 122, 117, 115, 120, 90,
- 118, 272, 272, 272, 126, 272, 86, 123, 87, 272,
- 88, 125, 112, 119, 89, 272, 113, 272, 124, 116,
- 127, 272, 117, 120, 90, 272, 118, 272, 128, 272,
- 126, 272, 130, 272, 135, 272, 136, 125, 119, 134,
-
- 131, 272, 129, 272, 272, 127, 132, 272, 133, 272,
- 272, 138, 272, 272, 128, 272, 140, 130, 142, 141,
- 135, 272, 136, 139, 134, 144, 131, 129, 137, 272,
- 272, 132, 143, 133, 272, 272, 138, 272, 272, 272,
- 145, 140, 147, 142, 149, 141, 148, 102, 139, 102,
- 144, 150, 153, 137, 152, 103, 99, 272, 143, 272,
- 151, 152, 103, 101, 161, 145, 272, 147, 104, 272,
- 149, 148, 272, 107, 272, 107, 150, 157, 153, 154,
- 152, 155, 272, 156, 158, 151, 158, 152, 159, 272,
- 161, 160, 272, 272, 104, 162, 272, 272, 163, 165,
-
- 272, 272, 272, 167, 166, 272, 272, 272, 169, 272,
- 272, 272, 173, 272, 164, 272, 160, 272, 272, 170,
- 171, 162, 168, 272, 163, 165, 172, 188, 272, 167,
- 166, 174, 272, 175, 169, 272, 272, 272, 173, 164,
- 272, 176, 177, 272, 170, 171, 180, 168, 178, 272,
- 272, 172, 188, 179, 272, 182, 174, 272, 175, 200,
- 183, 272, 272, 181, 272, 186, 272, 176, 177, 200,
- 272, 184, 180, 178, 187, 185, 191, 272, 179, 189,
- 272, 182, 190, 192, 272, 272, 183, 272, 181, 272,
- 194, 186, 272, 193, 272, 156, 184, 198, 197, 187,
-
- 272, 185, 191, 206, 189, 272, 195, 190, 154, 192,
- 154, 196, 198, 199, 272, 199, 194, 200, 193, 272,
- 156, 272, 203, 201, 197, 202, 272, 272, 206, 272,
- 272, 195, 272, 207, 272, 272, 196, 272, 208, 272,
- 272, 272, 272, 217, 272, 205, 215, 272, 203, 201,
- 202, 204, 272, 209, 210, 272, 272, 211, 212, 207,
- 213, 272, 214, 216, 208, 272, 232, 218, 217, 272,
- 205, 219, 215, 272, 272, 220, 204, 224, 209, 210,
- 222, 272, 211, 212, 272, 213, 221, 214, 216, 272,
- 272, 232, 272, 218, 228, 225, 272, 219, 227, 272,
-
- 223, 220, 224, 272, 229, 272, 222, 272, 272, 272,
- 226, 221, 230, 231, 234, 272, 272, 272, 235, 228,
- 237, 225, 272, 272, 227, 223, 233, 238, 239, 272,
- 229, 272, 272, 272, 272, 226, 236, 230, 241, 231,
- 234, 272, 272, 235, 272, 272, 237, 272, 240, 272,
- 244, 233, 242, 238, 239, 245, 272, 272, 247, 272,
- 272, 236, 243, 248, 241, 272, 246, 249, 272, 253,
- 272, 254, 272, 240, 272, 272, 244, 242, 259, 272,
- 250, 245, 272, 247, 256, 272, 251, 243, 252, 248,
- 272, 246, 249, 255, 272, 253, 254, 272, 272, 258,
-
- 257, 272, 261, 272, 259, 250, 272, 159, 260, 272,
- 256, 251, 159, 252, 157, 264, 272, 262, 255, 265,
- 272, 263, 266, 272, 267, 258, 257, 261, 272, 269,
- 272, 198, 268, 272, 260, 272, 271, 272, 270, 272,
- 264, 272, 262, 157, 265, 272, 263, 102, 266, 267,
- 97, 272, 272, 52, 48, 269, 272, 102, 268, 97,
- 272, 52, 271, 270, 36, 36, 36, 36, 46, 46,
- 46, 46, 96, 49, 96, 96, 100, 100, 48, 272,
- 37, 37, 7, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
-
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272
+ 105, 80, 92, 105, 53, 54, 61, 281, 281, 281,
+ 56, 281, 62, 281, 58, 59, 107, 281, 107, 281,
+ 108, 111, 60, 281, 110, 114, 105, 281, 108, 105,
+ 122, 61, 115, 281, 281, 281, 56, 62, 281, 281,
+ 86, 123, 87, 281, 88, 281, 111, 112, 89, 110,
+ 114, 113, 124, 281, 116, 122, 117, 115, 120, 90,
+ 118, 281, 281, 281, 126, 281, 86, 123, 87, 281,
+ 88, 125, 112, 119, 89, 281, 113, 281, 124, 116,
+ 127, 281, 117, 120, 90, 281, 118, 281, 128, 281,
+ 126, 130, 131, 281, 136, 281, 281, 125, 119, 135,
+
+ 132, 281, 129, 281, 281, 127, 133, 281, 134, 137,
+ 281, 139, 144, 281, 128, 143, 130, 131, 281, 140,
+ 136, 138, 141, 281, 135, 142, 132, 129, 145, 281,
+ 281, 133, 281, 134, 281, 137, 139, 281, 144, 150,
+ 143, 281, 157, 151, 140, 281, 138, 141, 281, 149,
+ 146, 142, 281, 145, 281, 148, 103, 99, 103, 101,
+ 152, 102, 153, 281, 104, 150, 154, 102, 151, 107,
+ 281, 107, 153, 158, 149, 146, 281, 281, 281, 155,
+ 148, 156, 281, 157, 163, 152, 281, 159, 153, 159,
+ 104, 160, 154, 281, 281, 161, 281, 167, 153, 162,
+
+ 281, 281, 164, 166, 281, 281, 168, 281, 165, 281,
+ 163, 281, 281, 170, 281, 281, 281, 281, 171, 174,
+ 161, 281, 178, 167, 173, 162, 169, 175, 164, 166,
+ 172, 176, 168, 165, 281, 281, 281, 180, 281, 170,
+ 177, 179, 182, 171, 281, 174, 281, 281, 178, 173,
+ 281, 169, 175, 281, 181, 172, 176, 187, 281, 184,
+ 281, 281, 180, 281, 183, 281, 177, 179, 182, 185,
+ 281, 186, 281, 188, 281, 190, 194, 281, 195, 181,
+ 193, 281, 281, 187, 281, 184, 281, 189, 197, 183,
+ 191, 281, 192, 281, 196, 185, 186, 200, 281, 188,
+
+ 190, 281, 194, 204, 195, 193, 199, 198, 281, 155,
+ 281, 155, 189, 201, 197, 191, 202, 192, 202, 196,
+ 203, 281, 157, 200, 281, 281, 281, 281, 205, 204,
+ 281, 199, 198, 206, 281, 281, 210, 281, 281, 281,
+ 211, 281, 281, 209, 281, 208, 207, 281, 281, 203,
+ 203, 281, 201, 205, 212, 281, 213, 281, 215, 206,
+ 214, 216, 210, 217, 221, 281, 211, 218, 209, 281,
+ 208, 207, 281, 228, 220, 219, 281, 281, 222, 212,
+ 281, 213, 223, 215, 281, 214, 216, 281, 217, 221,
+ 224, 281, 218, 225, 281, 281, 281, 226, 228, 220,
+
+ 281, 219, 227, 281, 222, 281, 230, 281, 223, 232,
+ 281, 281, 281, 281, 237, 229, 224, 281, 225, 270,
+ 233, 234, 236, 226, 235, 231, 281, 227, 281, 238,
+ 240, 281, 230, 281, 239, 232, 281, 281, 281, 237,
+ 229, 244, 245, 281, 270, 233, 241, 234, 236, 235,
+ 231, 281, 242, 243, 238, 240, 281, 246, 281, 281,
+ 239, 281, 247, 249, 281, 281, 281, 244, 245, 281,
+ 281, 241, 252, 281, 281, 253, 281, 242, 243, 254,
+ 248, 281, 256, 246, 250, 251, 281, 255, 247, 249,
+ 281, 281, 281, 257, 281, 258, 281, 281, 252, 262,
+
+ 281, 253, 259, 281, 254, 248, 260, 266, 256, 250,
+ 251, 261, 255, 269, 281, 263, 281, 264, 257, 281,
+ 258, 265, 281, 281, 267, 262, 281, 259, 281, 281,
+ 271, 260, 281, 266, 268, 275, 261, 273, 272, 269,
+ 263, 281, 264, 281, 274, 281, 281, 265, 281, 277,
+ 267, 281, 278, 281, 280, 271, 276, 281, 160, 160,
+ 268, 275, 273, 272, 158, 201, 279, 281, 281, 274,
+ 281, 281, 281, 158, 281, 277, 102, 97, 278, 281,
+ 280, 276, 281, 52, 48, 281, 102, 97, 281, 52,
+ 49, 279, 36, 36, 36, 36, 46, 46, 46, 46,
+
+ 96, 48, 96, 96, 100, 100, 281, 37, 37, 7,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281
} ;
-static yyconst flex_int16_t yy_chk[846] =
+static yyconst flex_int16_t yy_chk[873] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -586,90 +592,93 @@ static yyconst flex_int16_t yy_chk[846] =
1, 1, 5, 5, 5, 5, 5, 5, 5, 5,
5, 12, 12, 14, 14, 18, 19, 18, 21, 14,
21, 18, 22, 24, 25, 15, 25, 26, 22, 26,
- 33, 19, 33, 24, 25, 41, 41, 275, 32, 43,
+ 33, 19, 33, 24, 25, 41, 41, 284, 32, 43,
- 43, 271, 90, 18, 270, 14, 21, 18, 15, 34,
- 269, 34, 25, 32, 22, 26, 19, 267, 33, 24,
+ 43, 280, 90, 18, 279, 14, 21, 18, 15, 34,
+ 278, 34, 25, 32, 22, 26, 19, 276, 33, 24,
25, 90, 5, 5, 6, 6, 6, 6, 6, 6,
6, 6, 6, 15, 20, 23, 20, 34, 32, 29,
- 266, 29, 52, 23, 20, 29, 90, 52, 45, 45,
- 23, 31, 66, 20, 45, 28, 66, 27, 20, 253,
- 57, 31, 20, 252, 27, 28, 57, 29, 28, 23,
- 20, 29, 27, 52, 28, 23, 27, 31, 20, 249,
- 45, 246, 66, 20, 6, 6, 16, 31, 16, 16,
+ 275, 29, 52, 23, 20, 29, 90, 52, 45, 45,
+ 23, 31, 66, 20, 45, 28, 66, 27, 20, 262,
+ 57, 31, 20, 261, 27, 28, 57, 29, 28, 23,
+ 20, 29, 27, 52, 28, 23, 27, 31, 20, 260,
+ 45, 257, 66, 20, 6, 6, 16, 31, 16, 16,
27, 28, 57, 28, 51, 51, 16, 27, 53, 28,
51, 27, 31, 53, 54, 54, 16, 61, 59, 58,
- 54, 62, 16, 245, 16, 16, 56, 67, 56, 56,
- 56, 59, 16, 243, 58, 61, 51, 108, 108, 53,
+ 54, 62, 16, 254, 16, 16, 56, 67, 56, 56,
+ 56, 59, 16, 253, 58, 61, 51, 108, 108, 53,
67, 16, 62, 63, 60, 65, 54, 16, 30, 68,
- 30, 68, 30, 69, 30, 242, 59, 60, 30, 58,
+ 30, 68, 30, 69, 30, 251, 59, 60, 30, 58,
61, 60, 69, 64, 63, 67, 64, 62, 65, 30,
- 64, 70, 71, 240, 71, 72, 30, 68, 30, 234,
- 30, 70, 60, 64, 30, 233, 60, 74, 69, 63,
+ 64, 70, 71, 250, 71, 72, 30, 68, 30, 248,
+ 30, 70, 60, 64, 30, 243, 60, 74, 69, 63,
72, 73, 64, 65, 30, 77, 64, 78, 73, 75,
- 71, 80, 74, 76, 78, 82, 80, 70, 64, 77,
-
- 75, 84, 73, 81, 86, 72, 75, 83, 76, 232,
- 88, 82, 85, 89, 73, 226, 84, 74, 86, 85,
- 78, 91, 80, 83, 77, 88, 75, 73, 81, 92,
- 87, 75, 87, 76, 93, 222, 82, 95, 94, 219,
- 89, 84, 91, 86, 93, 85, 92, 102, 83, 103,
- 88, 94, 102, 81, 103, 99, 99, 217, 87, 110,
- 95, 99, 101, 101, 110, 89, 216, 91, 101, 214,
- 93, 92, 109, 105, 213, 105, 94, 105, 102, 104,
- 103, 104, 104, 104, 106, 95, 106, 99, 106, 115,
- 110, 109, 117, 120, 101, 115, 116, 118, 116, 118,
-
- 119, 121, 122, 120, 119, 123, 124, 126, 122, 212,
- 142, 125, 126, 211, 117, 127, 109, 128, 207, 123,
- 124, 115, 121, 203, 116, 118, 125, 142, 202, 120,
- 119, 127, 131, 128, 122, 129, 130, 133, 126, 117,
- 134, 129, 130, 135, 123, 124, 134, 121, 131, 136,
- 138, 125, 142, 133, 137, 136, 127, 140, 128, 200,
- 137, 141, 144, 135, 139, 140, 143, 129, 130, 199,
- 145, 138, 134, 131, 141, 139, 145, 146, 133, 143,
- 147, 136, 144, 146, 148, 149, 137, 168, 135, 150,
- 148, 140, 151, 147, 155, 155, 138, 198, 151, 141,
-
- 194, 139, 145, 168, 143, 161, 149, 144, 152, 146,
- 152, 150, 152, 153, 164, 153, 148, 153, 147, 156,
- 156, 160, 164, 160, 151, 161, 166, 170, 168, 165,
- 183, 149, 173, 170, 174, 176, 150, 177, 173, 178,
- 181, 179, 180, 183, 182, 166, 181, 206, 164, 160,
- 161, 165, 191, 174, 176, 184, 192, 177, 178, 170,
- 179, 185, 180, 182, 173, 186, 206, 185, 183, 187,
- 166, 186, 181, 188, 189, 187, 165, 192, 174, 176,
- 189, 197, 177, 178, 190, 179, 188, 180, 182, 193,
- 195, 206, 196, 185, 197, 193, 201, 186, 196, 204,
-
- 190, 187, 192, 205, 201, 210, 189, 208, 209, 175,
- 195, 188, 204, 205, 209, 215, 218, 172, 210, 197,
- 218, 193, 221, 220, 196, 190, 208, 220, 221, 223,
- 201, 171, 225, 169, 224, 195, 215, 204, 224, 205,
- 209, 231, 227, 210, 228, 230, 218, 236, 223, 229,
- 228, 208, 225, 220, 221, 229, 244, 235, 231, 237,
- 241, 215, 227, 235, 224, 238, 230, 236, 239, 241,
- 254, 244, 247, 223, 167, 163, 228, 225, 254, 256,
- 237, 229, 248, 231, 248, 162, 238, 227, 239, 235,
- 250, 230, 236, 247, 259, 241, 244, 251, 255, 251,
-
- 250, 257, 256, 260, 254, 237, 258, 159, 255, 262,
- 248, 238, 158, 239, 157, 259, 261, 257, 247, 260,
- 264, 258, 261, 265, 262, 251, 250, 256, 263, 264,
- 268, 154, 263, 132, 255, 114, 268, 113, 265, 112,
- 259, 111, 257, 107, 260, 100, 258, 98, 261, 262,
- 97, 79, 55, 50, 48, 264, 46, 44, 263, 39,
- 17, 13, 268, 265, 273, 273, 273, 273, 274, 274,
- 274, 274, 276, 11, 276, 276, 277, 277, 9, 7,
- 4, 3, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
-
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, 272, 272, 272
+ 71, 74, 74, 76, 78, 82, 81, 70, 64, 77,
+
+ 75, 86, 73, 83, 80, 72, 75, 84, 76, 80,
+ 87, 82, 87, 88, 73, 86, 74, 74, 85, 83,
+ 78, 81, 84, 89, 77, 85, 75, 73, 88, 93,
+ 94, 75, 92, 76, 91, 80, 82, 95, 87, 93,
+ 86, 156, 156, 94, 83, 241, 81, 84, 239, 92,
+ 89, 85, 238, 88, 237, 91, 99, 99, 101, 101,
+ 95, 102, 99, 231, 101, 93, 102, 103, 94, 105,
+ 226, 105, 103, 105, 92, 89, 109, 223, 115, 104,
+ 91, 104, 104, 104, 115, 95, 117, 106, 99, 106,
+ 101, 106, 102, 119, 110, 109, 120, 119, 103, 110,
+
+ 116, 118, 116, 118, 123, 121, 120, 122, 117, 125,
+ 115, 127, 130, 122, 126, 128, 124, 220, 123, 126,
+ 109, 132, 130, 119, 125, 110, 121, 127, 116, 118,
+ 124, 128, 120, 117, 129, 131, 135, 132, 134, 122,
+ 129, 131, 135, 123, 136, 126, 140, 218, 130, 125,
+ 139, 121, 127, 137, 134, 124, 128, 140, 143, 137,
+ 145, 217, 132, 138, 136, 141, 129, 131, 135, 138,
+ 146, 139, 147, 141, 142, 143, 146, 144, 147, 134,
+ 145, 148, 149, 140, 151, 137, 150, 142, 149, 136,
+ 144, 152, 144, 216, 148, 138, 139, 152, 215, 141,
+
+ 143, 161, 146, 161, 147, 145, 151, 150, 162, 153,
+ 210, 153, 142, 153, 149, 144, 154, 144, 154, 148,
+ 154, 157, 157, 152, 166, 165, 167, 169, 162, 161,
+ 171, 151, 150, 165, 174, 175, 171, 177, 179, 178,
+ 174, 206, 180, 169, 181, 167, 166, 182, 205, 203,
+ 202, 185, 201, 162, 175, 184, 177, 193, 179, 165,
+ 178, 180, 171, 181, 185, 197, 174, 182, 169, 183,
+ 167, 166, 187, 193, 184, 183, 188, 194, 187, 175,
+ 190, 177, 188, 179, 189, 178, 180, 192, 181, 185,
+ 189, 191, 182, 190, 195, 209, 265, 191, 193, 184,
+
+ 196, 183, 192, 199, 187, 198, 196, 200, 188, 199,
+ 211, 207, 208, 204, 209, 195, 189, 213, 190, 265,
+ 200, 204, 208, 191, 207, 198, 214, 192, 212, 211,
+ 213, 219, 196, 221, 212, 199, 186, 222, 224, 209,
+ 195, 222, 224, 176, 265, 200, 214, 204, 208, 207,
+ 198, 225, 219, 221, 211, 213, 227, 225, 235, 229,
+ 212, 228, 227, 229, 230, 232, 233, 222, 224, 234,
+ 236, 214, 233, 242, 244, 234, 240, 219, 221, 235,
+ 228, 245, 240, 225, 230, 232, 246, 236, 227, 229,
+ 249, 173, 247, 242, 172, 244, 255, 258, 233, 249,
+
+ 252, 234, 245, 264, 235, 228, 246, 258, 240, 230,
+ 232, 247, 236, 264, 266, 252, 268, 255, 242, 256,
+ 244, 256, 259, 267, 259, 249, 263, 245, 269, 270,
+ 266, 246, 170, 258, 263, 270, 247, 268, 267, 264,
+ 252, 271, 255, 273, 269, 272, 168, 256, 277, 272,
+ 259, 274, 273, 164, 277, 266, 271, 163, 160, 159,
+ 263, 270, 268, 267, 158, 155, 274, 133, 114, 269,
+ 113, 112, 111, 107, 100, 272, 98, 97, 273, 79,
+ 277, 271, 55, 50, 48, 46, 44, 39, 17, 13,
+ 11, 274, 282, 282, 282, 282, 283, 283, 283, 283,
+
+ 285, 9, 285, 285, 286, 286, 7, 4, 3, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
+ 281, 281
} ;
/* The intent behind this definition is that it'll catch
@@ -697,7 +706,7 @@ static yyconst flex_int16_t yy_chk[846] =
/* rules */
-#line 701 "envilex.C"
+#line 710 "envilex.C"
#define INITIAL 0
#define DISCARD 1
@@ -802,7 +811,7 @@ YY_DECL
#line 30 "envilex.L"
-#line 806 "envilex.C"
+#line 815 "envilex.C"
if ( !(yy_init) )
{
@@ -855,13 +864,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 273 )
+ if ( yy_current_state >= 282 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 272 );
+ while ( yy_current_state != 281 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -1042,144 +1051,159 @@ YY_RULE_SETUP
case 29:
YY_RULE_SETUP
#line 82 "envilex.L"
-{return LINES_;}
+{return LIMITS_;}
YY_BREAK
case 30:
YY_RULE_SETUP
#line 83 "envilex.L"
-{return MAJOR_;}
+{return LINES_;}
YY_BREAK
case 31:
YY_RULE_SETUP
#line 84 "envilex.L"
-{return MAP_;}
+{return MAJOR_;}
YY_BREAK
case 32:
YY_RULE_SETUP
#line 85 "envilex.L"
-{return MINOR_;}
+{return MAP_;}
YY_BREAK
case 33:
YY_RULE_SETUP
#line 86 "envilex.L"
-{return NAMES_;}
+{return MINOR_;}
YY_BREAK
case 34:
YY_RULE_SETUP
#line 87 "envilex.L"
-{return OFFSET_;}
+{return NAMES_;}
YY_BREAK
case 35:
YY_RULE_SETUP
#line 88 "envilex.L"
-{return OFFSETS_;}
+{return OFFSET_;}
YY_BREAK
case 36:
YY_RULE_SETUP
#line 89 "envilex.L"
-{return ORDER_;}
+{return OFFSETS_;}
YY_BREAK
case 37:
YY_RULE_SETUP
#line 90 "envilex.L"
-{return PIXEL_;}
+{return ORDER_;}
YY_BREAK
case 38:
YY_RULE_SETUP
#line 91 "envilex.L"
-{return PLOT_;}
+{return PIXEL_;}
YY_BREAK
case 39:
YY_RULE_SETUP
#line 92 "envilex.L"
-{return PROJECTION_;}
+{return PIXELS_;}
YY_BREAK
case 40:
YY_RULE_SETUP
#line 93 "envilex.L"
-{return RANGE_;}
+{return PLOT_;}
YY_BREAK
case 41:
YY_RULE_SETUP
#line 94 "envilex.L"
-{return REFLECTANCE_;}
+{return PROJECTION_;}
YY_BREAK
case 42:
YY_RULE_SETUP
#line 95 "envilex.L"
-{return SAMPLES_;}
+{return RANGE_;}
YY_BREAK
case 43:
YY_RULE_SETUP
#line 96 "envilex.L"
-{return SCALE_;}
+{return REFLECTANCE_;}
YY_BREAK
case 44:
YY_RULE_SETUP
#line 97 "envilex.L"
-{return SENSOR_;}
+{return SAMPLES_;}
YY_BREAK
case 45:
YY_RULE_SETUP
#line 98 "envilex.L"
-{return SIZE_;}
+{return SCALE_;}
YY_BREAK
case 46:
YY_RULE_SETUP
#line 99 "envilex.L"
-{return STRETCH_;}
+{return SCANNER_;}
YY_BREAK
case 47:
YY_RULE_SETUP
#line 100 "envilex.L"
-{return TITLES_;}
+{return SENSOR_;}
YY_BREAK
case 48:
YY_RULE_SETUP
#line 101 "envilex.L"
-{return TYPE_;}
+{return SIZE_;}
YY_BREAK
case 49:
YY_RULE_SETUP
#line 102 "envilex.L"
-{return UNITS_;}
+{return STRETCH_;}
YY_BREAK
case 50:
YY_RULE_SETUP
#line 103 "envilex.L"
-{return VALUE_;}
+{return TITLES_;}
YY_BREAK
case 51:
YY_RULE_SETUP
#line 104 "envilex.L"
-{return VALUES_;}
+{return TYPE_;}
YY_BREAK
case 52:
YY_RULE_SETUP
#line 105 "envilex.L"
-{return WAVELENGTH_;}
+{return UNITS_;}
YY_BREAK
case 53:
YY_RULE_SETUP
+#line 106 "envilex.L"
+{return VALUE_;}
+ YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 107 "envilex.L"
+{return VALUES_;}
+ YY_BREAK
+case 55:
+YY_RULE_SETUP
#line 108 "envilex.L"
+{return WAVELENGTH_;}
+ YY_BREAK
+case 56:
+YY_RULE_SETUP
+#line 111 "envilex.L"
{ // Integer
envilval->integer = atoi(yytext);
return INT;
}
YY_BREAK
-case 54:
-#line 114 "envilex.L"
-case 55:
+case 57:
+#line 117 "envilex.L"
+case 58:
YY_RULE_SETUP
-#line 114 "envilex.L"
+#line 117 "envilex.L"
{ // Real Number
envilval->real = atof(yytext);
return REAL;
}
YY_BREAK
-case 56:
+case 59:
YY_RULE_SETUP
-#line 120 "envilex.L"
+#line 123 "envilex.L"
{ // General String
int ll = yyleng <(ENVIPARSERSIZE-1) ? yyleng:(ENVIPARSERSIZE-1);
strncpy(envilval->str,yytext,ll);
@@ -1187,53 +1211,53 @@ YY_RULE_SETUP
return STRING;
}
YY_BREAK
-case 57:
+case 60:
YY_RULE_SETUP
-#line 127 "envilex.L"
+#line 130 "envilex.L"
{
return ',';
}
YY_BREAK
-case 58:
+case 61:
YY_RULE_SETUP
-#line 131 "envilex.L"
+#line 134 "envilex.L"
{ // White Spaces
}
YY_BREAK
-case 59:
-/* rule 59 can match eol */
+case 62:
+/* rule 62 can match eol */
YY_RULE_SETUP
-#line 134 "envilex.L"
+#line 137 "envilex.L"
{ // linefeed
}
YY_BREAK
-case 60:
+case 63:
YY_RULE_SETUP
-#line 137 "envilex.L"
+#line 140 "envilex.L"
{ // other chars, eat it
}
YY_BREAK
-case 61:
+case 64:
YY_RULE_SETUP
-#line 140 "envilex.L"
+#line 143 "envilex.L"
{ // Integer
envilval->integer = atoi(yytext);
return INT;
}
YY_BREAK
-case 62:
-#line 146 "envilex.L"
-case 63:
+case 65:
+#line 149 "envilex.L"
+case 66:
YY_RULE_SETUP
-#line 146 "envilex.L"
+#line 149 "envilex.L"
{ // Real Number
envilval->real = atof(yytext);
return REAL;
}
YY_BREAK
-case 64:
+case 67:
YY_RULE_SETUP
-#line 152 "envilex.L"
+#line 155 "envilex.L"
{ // General String
int ll = yyleng <(ENVIPARSERSIZE-1) ? yyleng:(ENVIPARSERSIZE-1);
strncpy(envilval->str,yytext,ll);
@@ -1241,24 +1265,24 @@ YY_RULE_SETUP
return STRING;
}
YY_BREAK
-case 65:
+case 68:
YY_RULE_SETUP
-#line 159 "envilex.L"
+#line 162 "envilex.L"
{ // White Spaces
}
YY_BREAK
-case 66:
-/* rule 66 can match eol */
+case 69:
+/* rule 69 can match eol */
YY_RULE_SETUP
-#line 162 "envilex.L"
+#line 165 "envilex.L"
{ // windows line feed
return '\n';
}
YY_BREAK
-case 67:
-/* rule 67 can match eol */
+case 70:
+/* rule 70 can match eol */
YY_RULE_SETUP
-#line 166 "envilex.L"
+#line 169 "envilex.L"
{ // linefeed
return '\n';
}
@@ -1266,24 +1290,24 @@ YY_RULE_SETUP
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(DISCARD):
case YY_STATE_EOF(BRACKET):
-#line 170 "envilex.L"
+#line 173 "envilex.L"
{ // eof
return EOF_;
}
YY_BREAK
-case 68:
+case 71:
YY_RULE_SETUP
-#line 174 "envilex.L"
+#line 177 "envilex.L"
{ // Else, return the char
return yytext[0];
}
YY_BREAK
-case 69:
+case 72:
YY_RULE_SETUP
-#line 178 "envilex.L"
+#line 181 "envilex.L"
ECHO;
YY_BREAK
-#line 1287 "envilex.C"
+#line 1311 "envilex.C"
case YY_END_OF_BUFFER:
{
@@ -1663,7 +1687,7 @@ int yyFlexLexer::yy_get_next_buffer()
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 273 )
+ if ( yy_current_state >= 282 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1691,11 +1715,11 @@ int yyFlexLexer::yy_get_next_buffer()
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 273 )
+ if ( yy_current_state >= 282 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 272);
+ yy_is_jam = (yy_current_state == 281);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -2180,7 +2204,7 @@ void envifree (void * ptr )
#define YYTABLES_NAME "yytables"
-#line 178 "envilex.L"
+#line 181 "envilex.L"
diff --git a/saotk/fitsy++/envilex.L b/saotk/fitsy++/envilex.L
index 440f8aa..dc4e655 100644
--- a/saotk/fitsy++/envilex.L
+++ b/saotk/fitsy++/envilex.L
@@ -79,6 +79,7 @@ header {return HEADER_;}
info {return INFO_;}
ignore {return IGNORE_;}
interleave {return INTERLEAVE_;}
+limits {return LIMITS_;}
lines {return LINES_;}
major {return MAJOR_;}
map {return MAP_;}
@@ -88,12 +89,14 @@ offset {return OFFSET_;}
offsets {return OFFSETS_;}
order {return ORDER_;}
pixel {return PIXEL_;}
+pixels {return PIXELS_;}
plot {return PLOT_;}
projection {return PROJECTION_;}
range {return RANGE_;}
reflectance {return REFLECTANCE_;}
samples {return SAMPLES_;}
scale {return SCALE_;}
+scanner {return SCANNER_;}
sensor {return SENSOR_;}
size {return SIZE_;}
stretch {return STRETCH_;}
diff --git a/saotk/fitsy++/enviparser.C b/saotk/fitsy++/enviparser.C
index b5fbb12..ab8c8ad 100644
--- a/saotk/fitsy++/enviparser.C
+++ b/saotk/fitsy++/enviparser.C
@@ -102,31 +102,34 @@
INFO_ = 283,
IGNORE_ = 284,
INTERLEAVE_ = 285,
- LINES_ = 286,
- MAJOR_ = 287,
- MAP_ = 288,
- MINOR_ = 289,
- NAMES_ = 290,
- OFFSET_ = 291,
- OFFSETS_ = 292,
- ORDER_ = 293,
- PIXEL_ = 294,
- PLOT_ = 295,
- PROJECTION_ = 296,
- RANGE_ = 297,
- REFLECTANCE_ = 298,
- SAMPLES_ = 299,
- SCALE_ = 300,
- SENSOR_ = 301,
- SIZE_ = 302,
- START_ = 303,
- STRETCH_ = 304,
- TITLES_ = 305,
- TYPE_ = 306,
- UNITS_ = 307,
- VALUE_ = 308,
- VALUES_ = 309,
- WAVELENGTH_ = 310
+ LIMITS_ = 286,
+ LINES_ = 287,
+ MAJOR_ = 288,
+ MAP_ = 289,
+ MINOR_ = 290,
+ NAMES_ = 291,
+ OFFSET_ = 292,
+ OFFSETS_ = 293,
+ ORDER_ = 294,
+ PIXEL_ = 295,
+ PIXELS_ = 296,
+ PLOT_ = 297,
+ PROJECTION_ = 298,
+ RANGE_ = 299,
+ REFLECTANCE_ = 300,
+ SAMPLES_ = 301,
+ SCALE_ = 302,
+ SCANNER_ = 303,
+ SENSOR_ = 304,
+ SIZE_ = 305,
+ START_ = 306,
+ STRETCH_ = 307,
+ TITLES_ = 308,
+ TYPE_ = 309,
+ UNITS_ = 310,
+ VALUE_ = 311,
+ VALUES_ = 312,
+ WAVELENGTH_ = 313
};
#endif
/* Tokens. */
@@ -158,31 +161,34 @@
#define INFO_ 283
#define IGNORE_ 284
#define INTERLEAVE_ 285
-#define LINES_ 286
-#define MAJOR_ 287
-#define MAP_ 288
-#define MINOR_ 289
-#define NAMES_ 290
-#define OFFSET_ 291
-#define OFFSETS_ 292
-#define ORDER_ 293
-#define PIXEL_ 294
-#define PLOT_ 295
-#define PROJECTION_ 296
-#define RANGE_ 297
-#define REFLECTANCE_ 298
-#define SAMPLES_ 299
-#define SCALE_ 300
-#define SENSOR_ 301
-#define SIZE_ 302
-#define START_ 303
-#define STRETCH_ 304
-#define TITLES_ 305
-#define TYPE_ 306
-#define UNITS_ 307
-#define VALUE_ 308
-#define VALUES_ 309
-#define WAVELENGTH_ 310
+#define LIMITS_ 286
+#define LINES_ 287
+#define MAJOR_ 288
+#define MAP_ 289
+#define MINOR_ 290
+#define NAMES_ 291
+#define OFFSET_ 292
+#define OFFSETS_ 293
+#define ORDER_ 294
+#define PIXEL_ 295
+#define PIXELS_ 296
+#define PLOT_ 297
+#define PROJECTION_ 298
+#define RANGE_ 299
+#define REFLECTANCE_ 300
+#define SAMPLES_ 301
+#define SCALE_ 302
+#define SCANNER_ 303
+#define SENSOR_ 304
+#define SIZE_ 305
+#define START_ 306
+#define STRETCH_ 307
+#define TITLES_ 308
+#define TYPE_ 309
+#define UNITS_ 310
+#define VALUE_ 311
+#define VALUES_ 312
+#define WAVELENGTH_ 313
@@ -237,7 +243,7 @@ typedef union YYSTYPE
char str[ENVIPARSERSIZE];
}
/* Line 193 of yacc.c. */
-#line 241 "enviparser.C"
+#line 247 "enviparser.C"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
@@ -250,7 +256,7 @@ typedef union YYSTYPE
/* Line 216 of yacc.c. */
-#line 254 "enviparser.C"
+#line 260 "enviparser.C"
#ifdef short
# undef short
@@ -463,22 +469,22 @@ union yyalloc
#endif
/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 63
+#define YYFINAL 65
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 192
+#define YYLAST 201
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 65
+#define YYNTOKENS 70
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 26
/* YYNRULES -- Number of rules. */
-#define YYNRULES 73
+#define YYNRULES 75
/* YYNRULES -- Number of states. */
-#define YYNSTATES 190
+#define YYNSTATES 198
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 310
+#define YYMAXUTOK 313
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -487,18 +493,18 @@ union yyalloc
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 61, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 66, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 64, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 60,
- 2, 56, 2, 2, 2, 2, 2, 2, 2, 2,
+ 63, 64, 2, 2, 69, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 65,
+ 2, 59, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 57, 58,
- 59, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 60, 61,
+ 62, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 62, 2, 63, 2, 2, 2, 2,
+ 2, 2, 2, 67, 2, 68, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -517,7 +523,7 @@ static const yytype_uint8 yytranslate[] =
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55
+ 55, 56, 57, 58
};
#if YYDEBUG
@@ -529,56 +535,58 @@ static const yytype_uint16 yyprhs[] =
26, 30, 34, 39, 45, 51, 52, 58, 63, 67,
68, 74, 79, 84, 89, 94, 99, 104, 109, 115,
121, 127, 133, 134, 141, 146, 151, 152, 157, 161,
- 165, 171, 177, 178, 182, 184, 186, 188, 190, 192,
- 194, 196, 198, 200, 202, 204, 207, 211, 214, 216,
- 220, 224, 226, 230, 234, 236, 255, 256, 261, 264,
- 267, 271, 275, 277
+ 165, 171, 177, 186, 187, 191, 193, 195, 197, 199,
+ 201, 203, 205, 207, 209, 211, 213, 216, 220, 223,
+ 225, 229, 233, 235, 239, 243, 245, 264, 265, 270,
+ 273, 276, 280, 284, 287, 289
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 66, 0, -1, 66, 67, 74, -1, 67, 74, -1,
- -1, 7, 76, -1, 72, -1, 21, -1, 20, 56,
- 80, -1, 44, 56, 4, -1, 31, 56, 4, -1,
- 12, 56, 4, -1, 27, 36, 56, 4, -1, 32,
- 23, 37, 56, 84, -1, 34, 23, 37, 56, 84,
- -1, -1, 24, 51, 56, 68, 6, -1, 18, 51,
- 56, 77, -1, 30, 56, 78, -1, -1, 46, 51,
- 56, 69, 6, -1, 17, 38, 56, 79, -1, 57,
- 48, 56, 84, -1, 58, 48, 56, 84, -1, 33,
- 28, 56, 86, -1, 41, 28, 56, 80, -1, 19,
- 12, 56, 84, -1, 55, 52, 56, 6, -1, 43,
- 45, 22, 56, 75, -1, 59, 40, 42, 56, 82,
- -1, 59, 40, 10, 56, 82, -1, 59, 40, 50,
- 56, 80, -1, -1, 18, 29, 54, 56, 70, 6,
- -1, 39, 47, 56, 82, -1, 11, 35, 56, 80,
- -1, -1, 55, 56, 71, 88, -1, 25, 56, 80,
- -1, 13, 56, 80, -1, 18, 26, 54, 56, 82,
- -1, 18, 36, 54, 56, 82, -1, -1, 60, 73,
- 6, -1, 61, -1, 3, -1, 5, -1, 4, -1,
- 8, -1, 9, -1, 4, -1, 16, -1, 15, -1,
- 14, -1, 4, -1, 62, 63, -1, 62, 81, 63,
- -1, 81, 6, -1, 6, -1, 62, 83, 63, -1,
- 83, 64, 75, -1, 75, -1, 62, 85, 63, -1,
- 85, 64, 4, -1, 4, -1, 62, 6, 64, 4,
- 64, 4, 64, 75, 64, 75, 64, 75, 64, 75,
- 64, 4, 87, 63, -1, -1, 64, 6, 64, 6,
- -1, 64, 6, -1, 62, 63, -1, 62, 89, 63,
- -1, 89, 64, 90, -1, 90, -1, 75, -1
+ 71, 0, -1, 71, 72, 79, -1, 72, 79, -1,
+ -1, 7, 81, -1, 77, -1, 21, -1, 20, 59,
+ 85, -1, 46, 59, 4, -1, 32, 59, 4, -1,
+ 12, 59, 4, -1, 27, 37, 59, 4, -1, 33,
+ 23, 38, 59, 89, -1, 35, 23, 38, 59, 89,
+ -1, -1, 24, 54, 59, 73, 6, -1, 18, 54,
+ 59, 82, -1, 30, 59, 83, -1, -1, 49, 54,
+ 59, 74, 6, -1, 17, 39, 59, 84, -1, 60,
+ 51, 59, 89, -1, 61, 51, 59, 89, -1, 34,
+ 28, 59, 91, -1, 43, 28, 59, 85, -1, 19,
+ 12, 59, 89, -1, 58, 55, 59, 6, -1, 45,
+ 47, 22, 59, 80, -1, 62, 42, 44, 59, 87,
+ -1, 62, 42, 10, 59, 87, -1, 62, 42, 53,
+ 59, 85, -1, -1, 18, 29, 57, 59, 75, 6,
+ -1, 40, 50, 59, 87, -1, 11, 36, 59, 85,
+ -1, -1, 58, 59, 76, 93, -1, 25, 59, 85,
+ -1, 13, 59, 85, -1, 18, 26, 57, 59, 87,
+ -1, 18, 37, 57, 59, 87, -1, 48, 31, 63,
+ 41, 64, 59, 4, 4, -1, -1, 65, 78, 6,
+ -1, 66, -1, 3, -1, 5, -1, 4, -1, 8,
+ -1, 9, -1, 4, -1, 16, -1, 15, -1, 14,
+ -1, 4, -1, 67, 68, -1, 67, 86, 68, -1,
+ 86, 6, -1, 6, -1, 67, 88, 68, -1, 88,
+ 69, 80, -1, 80, -1, 67, 90, 68, -1, 90,
+ 69, 4, -1, 4, -1, 67, 6, 69, 4, 69,
+ 4, 69, 80, 69, 80, 69, 80, 69, 80, 69,
+ 4, 92, 68, -1, -1, 69, 6, 69, 6, -1,
+ 69, 6, -1, 67, 68, -1, 67, 94, 68, -1,
+ 94, 69, 95, -1, 94, 69, -1, 95, -1, 80,
+ -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 101, 101, 102, 105, 106, 107, 108, 109, 110,
- 111, 112, 113, 114, 115, 116, 116, 117, 118, 119,
- 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
- 129, 130, 131, 131, 132, 133, 134, 134, 135, 136,
- 137, 138, 141, 141, 144, 145, 148, 149, 152, 153,
- 156, 186, 187, 188, 191, 204, 205, 208, 209, 212,
- 215, 216, 219, 222, 223, 226, 229, 230, 231, 234,
- 240, 255, 256, 259
+ 0, 104, 104, 105, 108, 109, 110, 111, 112, 113,
+ 114, 115, 116, 117, 118, 119, 119, 120, 121, 122,
+ 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,
+ 132, 133, 134, 134, 135, 136, 137, 137, 138, 139,
+ 140, 141, 142, 145, 145, 148, 149, 152, 153, 156,
+ 157, 160, 190, 191, 192, 195, 208, 209, 212, 213,
+ 216, 219, 220, 223, 226, 227, 230, 233, 234, 235,
+ 238, 244, 259, 260, 261, 264
};
#endif
@@ -591,15 +599,16 @@ static const char *const yytname[] =
"DEBUG_", "ON_", "OFF_", "AVERAGE_", "BAND_", "BANDS_", "BBL_", "BIL_",
"BIP_", "BSQ_", "BYTE_", "DATA_", "DEFAULT_", "DESCRIPTION_", "ENVI_",
"FACTOR_", "FRAME_", "FILE_", "FWHM_", "GAIN_", "HEADER_", "INFO_",
- "IGNORE_", "INTERLEAVE_", "LINES_", "MAJOR_", "MAP_", "MINOR_", "NAMES_",
- "OFFSET_", "OFFSETS_", "ORDER_", "PIXEL_", "PLOT_", "PROJECTION_",
- "RANGE_", "REFLECTANCE_", "SAMPLES_", "SCALE_", "SENSOR_", "SIZE_",
- "START_", "STRETCH_", "TITLES_", "TYPE_", "UNITS_", "VALUE_", "VALUES_",
- "WAVELENGTH_", "'='", "'X'", "'Y'", "'Z'", "';'", "'\\n'", "'{'", "'}'",
- "','", "$accept", "commands", "command", "@1", "@2", "@3", "@4",
- "comment", "@5", "terminator", "numeric", "debug", "bitpix", "encoding",
- "endian", "liststr", "strings", "listnum", "numerics", "listint", "ints",
- "listmap", "listmapopt", "listwave", "aWaves", "aWave", 0
+ "IGNORE_", "INTERLEAVE_", "LIMITS_", "LINES_", "MAJOR_", "MAP_",
+ "MINOR_", "NAMES_", "OFFSET_", "OFFSETS_", "ORDER_", "PIXEL_", "PIXELS_",
+ "PLOT_", "PROJECTION_", "RANGE_", "REFLECTANCE_", "SAMPLES_", "SCALE_",
+ "SCANNER_", "SENSOR_", "SIZE_", "START_", "STRETCH_", "TITLES_", "TYPE_",
+ "UNITS_", "VALUE_", "VALUES_", "WAVELENGTH_", "'='", "'X'", "'Y'", "'Z'",
+ "'('", "')'", "';'", "'\\n'", "'{'", "'}'", "','", "$accept", "commands",
+ "command", "@1", "@2", "@3", "@4", "comment", "@5", "terminator",
+ "numeric", "debug", "bitpix", "encoding", "endian", "liststr", "strings",
+ "listnum", "numerics", "listint", "ints", "listmap", "listmapopt",
+ "listwave", "aWaves", "aWave", 0
};
#endif
@@ -613,22 +622,22 @@ static const yytype_uint16 yytoknum[] =
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
- 305, 306, 307, 308, 309, 310, 61, 88, 89, 90,
- 59, 10, 123, 125, 44
+ 305, 306, 307, 308, 309, 310, 311, 312, 313, 61,
+ 88, 89, 90, 40, 41, 59, 10, 123, 125, 44
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 65, 66, 66, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, 67, 68, 67, 67, 67, 69,
- 67, 67, 67, 67, 67, 67, 67, 67, 67, 67,
- 67, 67, 70, 67, 67, 67, 71, 67, 67, 67,
- 67, 67, 73, 72, 74, 74, 75, 75, 76, 76,
- 77, 78, 78, 78, 79, 80, 80, 81, 81, 82,
- 83, 83, 84, 85, 85, 86, 87, 87, 87, 88,
- 88, 89, 89, 90
+ 0, 70, 71, 71, 72, 72, 72, 72, 72, 72,
+ 72, 72, 72, 72, 72, 73, 72, 72, 72, 74,
+ 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
+ 72, 72, 75, 72, 72, 72, 76, 72, 72, 72,
+ 72, 72, 72, 78, 77, 79, 79, 80, 80, 81,
+ 81, 82, 83, 83, 83, 84, 85, 85, 86, 86,
+ 87, 88, 88, 89, 90, 90, 91, 92, 92, 92,
+ 93, 93, 94, 94, 94, 95
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -638,10 +647,10 @@ static const yytype_uint8 yyr2[] =
3, 3, 4, 5, 5, 0, 5, 4, 3, 0,
5, 4, 4, 4, 4, 4, 4, 4, 5, 5,
5, 5, 0, 6, 4, 4, 0, 4, 3, 3,
- 5, 5, 0, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 2, 3, 2, 1, 3,
- 3, 1, 3, 3, 1, 18, 0, 4, 2, 2,
- 3, 3, 1, 1
+ 5, 5, 8, 0, 3, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 3, 2, 1,
+ 3, 3, 1, 3, 3, 1, 18, 0, 4, 2,
+ 2, 3, 3, 2, 1, 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -651,65 +660,67 @@ static const yytype_uint8 yydefact[] =
{
4, 0, 0, 0, 0, 0, 0, 0, 0, 7,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 42, 4, 0,
- 6, 48, 49, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 43, 4,
+ 0, 6, 49, 50, 5, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 36, 0,
- 0, 0, 0, 1, 0, 45, 44, 3, 0, 11,
- 0, 39, 0, 0, 0, 0, 0, 0, 8, 15,
- 38, 0, 53, 52, 51, 18, 10, 0, 0, 0,
- 0, 0, 0, 9, 19, 0, 0, 0, 0, 0,
- 0, 0, 43, 2, 35, 58, 55, 0, 54, 21,
- 0, 32, 0, 50, 17, 0, 26, 0, 12, 0,
- 0, 24, 0, 0, 34, 25, 0, 0, 27, 0,
- 37, 22, 23, 0, 0, 0, 57, 56, 40, 0,
- 41, 64, 0, 16, 13, 0, 14, 47, 46, 61,
- 0, 28, 20, 69, 73, 0, 72, 30, 29, 31,
- 33, 62, 0, 0, 59, 0, 70, 0, 63, 0,
- 60, 71, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 66, 0, 0, 68, 65, 0, 67
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 36, 0, 0, 0, 0, 1, 0, 46, 45, 3,
+ 0, 11, 0, 39, 0, 0, 0, 0, 0, 0,
+ 8, 15, 38, 0, 54, 53, 52, 18, 10, 0,
+ 0, 0, 0, 0, 0, 9, 0, 19, 0, 0,
+ 0, 0, 0, 0, 0, 44, 2, 35, 59, 56,
+ 0, 55, 21, 0, 32, 0, 51, 17, 0, 26,
+ 0, 12, 0, 0, 24, 0, 0, 34, 25, 0,
+ 0, 0, 27, 0, 37, 22, 23, 0, 0, 0,
+ 58, 57, 40, 0, 41, 65, 0, 16, 13, 0,
+ 14, 48, 47, 62, 0, 28, 0, 20, 70, 75,
+ 0, 74, 30, 29, 31, 33, 63, 0, 0, 60,
+ 0, 0, 71, 73, 64, 0, 61, 0, 72, 0,
+ 42, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 67, 0, 0, 69, 66, 0, 68
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 28, 29, 117, 127, 139, 96, 30, 62, 67,
- 154, 33, 114, 85, 109, 71, 107, 124, 150, 116,
- 142, 121, 185, 130, 155, 156
+ -1, 29, 30, 120, 131, 143, 99, 31, 64, 69,
+ 159, 34, 117, 87, 112, 73, 110, 127, 154, 119,
+ 146, 124, 193, 134, 160, 161
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -98
+#define YYPACT_NINF -91
static const yytype_int16 yypact[] =
{
- 77, 23, -31, -47, -39, -25, 88, 27, -15, -98,
- -6, -5, 30, 11, 24, 59, 63, 64, 46, 71,
- 55, 47, 54, -45, 58, 65, 72, -98, 3, -2,
- -98, -98, -98, -98, 66, 111, 57, 69, 73, 74,
- 75, 70, 82, 57, 84, 57, 85, 39, 126, 94,
- 86, 96, 87, 89, 122, 142, 91, 92, -98, 93,
- 95, 28, 144, -98, -2, -98, -98, -98, 57, -98,
- 2, -98, 148, 97, 98, 99, 152, 100, -98, -98,
- -98, 153, -98, -98, -98, -98, -98, 102, 101, 103,
- 104, 57, 105, -98, -98, 154, 106, 100, 100, 108,
- 109, 113, -98, -98, -98, -98, -98, 6, -98, -98,
- 104, -98, 104, -98, -98, 163, -98, 164, -98, 100,
- 165, -98, 100, 52, -98, -98, 52, 166, -98, 1,
- -98, -98, -98, 104, 104, 57, -98, -98, -98, 167,
- -98, -98, 8, -98, -98, 110, -98, -98, -98, -98,
- 12, -98, -98, -98, -98, 22, -98, -98, -98, -98,
- -98, -98, 171, 172, -98, 52, -98, 52, -98, 114,
- -98, -98, 173, 115, 52, 116, 52, 117, 52, 118,
- 52, 119, 180, 121, 181, 123, 124, -98, 183, -98
+ 90, 11, -30, -47, -41, -24, -21, 26, -27, -91,
+ -13, -8, 37, 19, 22, 56, 55, 61, 39, 62,
+ 44, 34, 68, 46, -46, 53, 54, 64, -91, 10,
+ -2, -91, -91, -91, -91, 57, 108, 51, 60, 69,
+ 70, 71, 73, 75, 51, 78, 51, 81, 72, 109,
+ 83, 82, 91, 84, 85, 120, 127, 86, 87, 88,
+ -91, 94, 95, 4, 139, -91, -2, -91, -91, -91,
+ 51, -91, 1, -91, 152, 98, 99, 100, 156, 96,
+ -91, -91, -91, 157, -91, -91, -91, -91, -91, 103,
+ 97, 106, 101, 51, 107, -91, 126, -91, 163, 104,
+ 96, 96, 111, 113, 114, -91, -91, -91, -91, -91,
+ 5, -91, -91, 101, -91, 101, -91, -91, 170, -91,
+ 169, -91, 96, 171, -91, 96, 20, -91, -91, 20,
+ 112, 172, -91, -1, -91, -91, -91, 101, 101, 51,
+ -91, -91, -91, 173, -91, -91, -22, -91, -91, 115,
+ -91, -91, -91, -91, -6, -91, 121, -91, -91, -91,
+ -3, -91, -91, -91, -91, -91, -91, 177, 178, -91,
+ 20, 179, -91, 20, -91, 116, -91, 182, -91, 183,
+ -91, 119, 20, 122, 20, 123, 20, 124, 20, 125,
+ 185, 128, 184, 130, 131, -91, 189, -91
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int16 yypgoto[] =
{
- -98, -98, 162, -98, -98, -98, -98, -98, -98, 127,
- -97, -98, -98, -98, -98, -43, -98, -60, -98, -79,
- -98, -98, -98, -98, -98, 25
+ -91, -91, 167, -91, -91, -91, -91, -91, -91, 133,
+ -90, -91, -91, -91, -91, -44, -91, -61, -91, -40,
+ -91, -91, -91, -91, -91, 28
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -719,50 +730,52 @@ static const yytype_int16 yypgoto[] =
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
- 78, 65, 80, 63, 34, 147, 148, 57, 105, 35,
- 1, 58, 136, 37, 2, 3, 4, 36, 131, 132,
- 5, 6, 7, 8, 9, 104, 149, 10, 11, 151,
- 12, 31, 32, 13, 14, 15, 16, 17, 99, 42,
- 144, 43, 18, 146, 19, 44, 20, 21, 125, 22,
- 138, 45, 140, 82, 83, 84, 147, 148, 23, 66,
- 24, 25, 26, 27, 153, 106, 46, 47, 170, 137,
- 100, 161, 162, 157, 158, 164, 165, 175, 101, 177,
- 48, 179, 49, 181, 1, 166, 167, 51, 2, 3,
- 4, 50, 159, 52, 5, 6, 7, 8, 9, 53,
- 54, 10, 11, 55, 12, 56, 59, 13, 14, 15,
- 16, 17, 61, 60, 38, 69, 18, 39, 19, 70,
- 20, 21, 68, 22, 40, 72, 76, 73, 74, 75,
- 86, 87, 23, 89, 24, 25, 26, 27, 77, 41,
- 79, 81, 88, 90, 92, 91, 93, 94, 95, 97,
- 102, 98, 108, 110, 111, 112, 113, 118, 119, 122,
- 128, 126, 115, 120, 133, 134, 123, 141, 129, 135,
- 143, 145, 152, 160, 163, 168, 169, 173, 172, 174,
- 176, 178, 180, 182, 183, 184, 187, 186, 188, 189,
- 64, 103, 171
+ 80, 67, 82, 151, 152, 39, 35, 108, 40, 59,
+ 65, 140, 36, 60, 102, 38, 41, 1, 37, 32,
+ 33, 2, 3, 4, 151, 152, 107, 5, 6, 7,
+ 8, 9, 44, 42, 10, 11, 153, 12, 43, 155,
+ 13, 45, 14, 15, 16, 17, 166, 167, 103, 128,
+ 18, 46, 142, 19, 144, 20, 21, 104, 22, 23,
+ 135, 136, 169, 170, 68, 172, 173, 158, 24, 109,
+ 25, 26, 27, 141, 47, 28, 162, 163, 48, 50,
+ 176, 49, 148, 51, 52, 150, 84, 85, 86, 53,
+ 54, 55, 183, 56, 185, 164, 187, 1, 189, 57,
+ 58, 2, 3, 4, 61, 62, 63, 5, 6, 7,
+ 8, 9, 71, 88, 10, 11, 70, 12, 72, 74,
+ 13, 89, 14, 15, 16, 17, 75, 76, 77, 91,
+ 18, 95, 78, 19, 79, 20, 21, 81, 22, 23,
+ 83, 90, 94, 92, 93, 105, 97, 98, 24, 96,
+ 25, 26, 27, 100, 101, 28, 111, 113, 114, 115,
+ 116, 121, 122, 118, 123, 125, 129, 130, 126, 132,
+ 137, 133, 138, 139, 145, 147, 156, 149, 157, 165,
+ 171, 174, 175, 177, 168, 179, 180, 181, 182, 191,
+ 194, 184, 186, 188, 190, 197, 66, 192, 195, 106,
+ 196, 178
};
static const yytype_uint8 yycheck[] =
{
- 43, 3, 45, 0, 35, 4, 5, 52, 6, 56,
- 7, 56, 6, 38, 11, 12, 13, 56, 97, 98,
- 17, 18, 19, 20, 21, 68, 123, 24, 25, 126,
- 27, 8, 9, 30, 31, 32, 33, 34, 10, 12,
- 119, 56, 39, 122, 41, 51, 43, 44, 91, 46,
- 110, 56, 112, 14, 15, 16, 4, 5, 55, 61,
- 57, 58, 59, 60, 63, 63, 36, 56, 165, 63,
- 42, 63, 64, 133, 134, 63, 64, 174, 50, 176,
- 56, 178, 23, 180, 7, 63, 64, 23, 11, 12,
- 13, 28, 135, 47, 17, 18, 19, 20, 21, 28,
- 45, 24, 25, 56, 27, 51, 48, 30, 31, 32,
- 33, 34, 40, 48, 26, 4, 39, 29, 41, 62,
- 43, 44, 56, 46, 36, 56, 56, 54, 54, 54,
- 4, 37, 55, 37, 57, 58, 59, 60, 56, 51,
- 56, 56, 56, 56, 22, 56, 4, 56, 56, 56,
- 6, 56, 4, 56, 56, 56, 4, 4, 56, 56,
- 6, 56, 62, 62, 56, 56, 62, 4, 62, 56,
- 6, 6, 6, 6, 64, 4, 4, 4, 64, 64,
- 64, 64, 64, 64, 4, 64, 63, 6, 64, 6,
- 28, 64, 167
+ 44, 3, 46, 4, 5, 26, 36, 6, 29, 55,
+ 0, 6, 59, 59, 10, 39, 37, 7, 59, 8,
+ 9, 11, 12, 13, 4, 5, 70, 17, 18, 19,
+ 20, 21, 59, 54, 24, 25, 126, 27, 12, 129,
+ 30, 54, 32, 33, 34, 35, 68, 69, 44, 93,
+ 40, 59, 113, 43, 115, 45, 46, 53, 48, 49,
+ 100, 101, 68, 69, 66, 68, 69, 68, 58, 68,
+ 60, 61, 62, 68, 37, 65, 137, 138, 59, 23,
+ 170, 59, 122, 28, 23, 125, 14, 15, 16, 50,
+ 28, 47, 182, 59, 184, 139, 186, 7, 188, 31,
+ 54, 11, 12, 13, 51, 51, 42, 17, 18, 19,
+ 20, 21, 4, 4, 24, 25, 59, 27, 67, 59,
+ 30, 38, 32, 33, 34, 35, 57, 57, 57, 38,
+ 40, 4, 59, 43, 59, 45, 46, 59, 48, 49,
+ 59, 59, 22, 59, 59, 6, 59, 59, 58, 63,
+ 60, 61, 62, 59, 59, 65, 4, 59, 59, 59,
+ 4, 4, 59, 67, 67, 59, 59, 41, 67, 6,
+ 59, 67, 59, 59, 4, 6, 64, 6, 6, 6,
+ 59, 4, 4, 4, 69, 69, 4, 4, 69, 4,
+ 6, 69, 69, 69, 69, 6, 29, 69, 68, 66,
+ 69, 173
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -770,24 +783,25 @@ static const yytype_uint8 yycheck[] =
static const yytype_uint8 yystos[] =
{
0, 7, 11, 12, 13, 17, 18, 19, 20, 21,
- 24, 25, 27, 30, 31, 32, 33, 34, 39, 41,
- 43, 44, 46, 55, 57, 58, 59, 60, 66, 67,
- 72, 8, 9, 76, 35, 56, 56, 38, 26, 29,
- 36, 51, 12, 56, 51, 56, 36, 56, 56, 23,
- 28, 23, 47, 28, 45, 56, 51, 52, 56, 48,
- 48, 40, 73, 0, 67, 3, 61, 74, 56, 4,
- 62, 80, 56, 54, 54, 54, 56, 56, 80, 56,
- 80, 56, 14, 15, 16, 78, 4, 37, 56, 37,
- 56, 56, 22, 4, 56, 56, 71, 56, 56, 10,
- 42, 50, 6, 74, 80, 6, 63, 81, 4, 79,
- 56, 56, 56, 4, 77, 62, 84, 68, 4, 56,
- 62, 86, 56, 62, 82, 80, 56, 69, 6, 62,
- 88, 84, 84, 56, 56, 56, 6, 63, 82, 70,
- 82, 4, 85, 6, 84, 6, 84, 4, 5, 75,
- 83, 75, 6, 63, 75, 89, 90, 82, 82, 80,
- 6, 63, 64, 64, 63, 64, 63, 64, 4, 4,
- 75, 90, 64, 4, 64, 75, 64, 75, 64, 75,
- 64, 75, 64, 4, 64, 87, 6, 63, 64, 6
+ 24, 25, 27, 30, 32, 33, 34, 35, 40, 43,
+ 45, 46, 48, 49, 58, 60, 61, 62, 65, 71,
+ 72, 77, 8, 9, 81, 36, 59, 59, 39, 26,
+ 29, 37, 54, 12, 59, 54, 59, 37, 59, 59,
+ 23, 28, 23, 50, 28, 47, 59, 31, 54, 55,
+ 59, 51, 51, 42, 78, 0, 72, 3, 66, 79,
+ 59, 4, 67, 85, 59, 57, 57, 57, 59, 59,
+ 85, 59, 85, 59, 14, 15, 16, 83, 4, 38,
+ 59, 38, 59, 59, 22, 4, 63, 59, 59, 76,
+ 59, 59, 10, 44, 53, 6, 79, 85, 6, 68,
+ 86, 4, 84, 59, 59, 59, 4, 82, 67, 89,
+ 73, 4, 59, 67, 91, 59, 67, 87, 85, 59,
+ 41, 74, 6, 67, 93, 89, 89, 59, 59, 59,
+ 6, 68, 87, 75, 87, 4, 90, 6, 89, 6,
+ 89, 4, 5, 80, 88, 80, 64, 6, 68, 80,
+ 94, 95, 87, 87, 85, 6, 68, 69, 69, 68,
+ 69, 59, 68, 69, 4, 4, 80, 4, 95, 69,
+ 4, 4, 69, 80, 69, 80, 69, 80, 69, 80,
+ 69, 4, 69, 92, 6, 68, 69, 6
};
#define yyerrok (yyerrstatus = 0)
@@ -1615,77 +1629,77 @@ yyreduce:
switch (yyn)
{
case 9:
-#line 110 "enviparser.Y"
+#line 113 "enviparser.Y"
{envi->setpWidth((yyvsp[(3) - (3)].integer));;}
break;
case 10:
-#line 111 "enviparser.Y"
+#line 114 "enviparser.Y"
{envi->setpHeight((yyvsp[(3) - (3)].integer));;}
break;
case 11:
-#line 112 "enviparser.Y"
+#line 115 "enviparser.Y"
{envi->setpDepth((yyvsp[(3) - (3)].integer));;}
break;
case 12:
-#line 113 "enviparser.Y"
+#line 116 "enviparser.Y"
{envi->setpSkip((yyvsp[(4) - (4)].integer));;}
break;
case 15:
-#line 116 "enviparser.Y"
+#line 119 "enviparser.Y"
{DISCARD_(1);}
break;
case 19:
-#line 119 "enviparser.Y"
+#line 122 "enviparser.Y"
{DISCARD_(1);}
break;
case 32:
-#line 131 "enviparser.Y"
+#line 134 "enviparser.Y"
{DISCARD_(1);}
break;
case 36:
-#line 134 "enviparser.Y"
+#line 137 "enviparser.Y"
{numWave=0;;}
break;
- case 42:
-#line 141 "enviparser.Y"
+ case 43:
+#line 145 "enviparser.Y"
{DISCARD_(1);}
break;
- case 45:
-#line 145 "enviparser.Y"
+ case 46:
+#line 149 "enviparser.Y"
{YYACCEPT;;}
break;
- case 46:
-#line 148 "enviparser.Y"
+ case 47:
+#line 152 "enviparser.Y"
{(yyval.real)=(yyvsp[(1) - (1)].real);;}
break;
- case 47:
-#line 149 "enviparser.Y"
+ case 48:
+#line 153 "enviparser.Y"
{(yyval.real)=(yyvsp[(1) - (1)].integer);;}
break;
- case 48:
-#line 152 "enviparser.Y"
+ case 49:
+#line 156 "enviparser.Y"
{yydebug=1;;}
break;
- case 49:
-#line 153 "enviparser.Y"
+ case 50:
+#line 157 "enviparser.Y"
{yydebug=0;;}
break;
- case 50:
-#line 157 "enviparser.Y"
+ case 51:
+#line 161 "enviparser.Y"
{
switch((yyvsp[(1) - (1)].integer)) {
case 1:
@@ -1715,23 +1729,23 @@ yyreduce:
;}
break;
- case 51:
-#line 186 "enviparser.Y"
+ case 52:
+#line 190 "enviparser.Y"
{envi->setpEncoding(FitsFile::BSQ);;}
break;
- case 52:
-#line 187 "enviparser.Y"
+ case 53:
+#line 191 "enviparser.Y"
{envi->setpEncoding(FitsFile::BIP);;}
break;
- case 53:
-#line 188 "enviparser.Y"
+ case 54:
+#line 192 "enviparser.Y"
{envi->setpEncoding(FitsFile::BIL);;}
break;
- case 54:
-#line 192 "enviparser.Y"
+ case 55:
+#line 196 "enviparser.Y"
{
switch((yyvsp[(1) - (1)].integer)) {
case 0:
@@ -1744,8 +1758,8 @@ yyreduce:
;}
break;
- case 69:
-#line 235 "enviparser.Y"
+ case 70:
+#line 239 "enviparser.Y"
{
envi->setpCRPIX3(1);
envi->setpCRVAL3(1);
@@ -1753,8 +1767,8 @@ yyreduce:
;}
break;
- case 70:
-#line 241 "enviparser.Y"
+ case 71:
+#line 245 "enviparser.Y"
{
if (numWave>=2) {
envi->setpCRPIX3(1);
@@ -1769,8 +1783,8 @@ yyreduce:
;}
break;
- case 73:
-#line 260 "enviparser.Y"
+ case 75:
+#line 265 "enviparser.Y"
{
if (numWave < MAXWAVES)
wave[numWave++] = (yyvsp[(1) - (1)].real);
@@ -1779,7 +1793,7 @@ yyreduce:
/* Line 1267 of yacc.c. */
-#line 1783 "enviparser.C"
+#line 1797 "enviparser.C"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1993,6 +2007,6 @@ yyreturn:
}
-#line 266 "enviparser.Y"
+#line 271 "enviparser.Y"
diff --git a/saotk/fitsy++/enviparser.H b/saotk/fitsy++/enviparser.H
index a2b3e31..087fd44 100644
--- a/saotk/fitsy++/enviparser.H
+++ b/saotk/fitsy++/enviparser.H
@@ -67,31 +67,34 @@
INFO_ = 283,
IGNORE_ = 284,
INTERLEAVE_ = 285,
- LINES_ = 286,
- MAJOR_ = 287,
- MAP_ = 288,
- MINOR_ = 289,
- NAMES_ = 290,
- OFFSET_ = 291,
- OFFSETS_ = 292,
- ORDER_ = 293,
- PIXEL_ = 294,
- PLOT_ = 295,
- PROJECTION_ = 296,
- RANGE_ = 297,
- REFLECTANCE_ = 298,
- SAMPLES_ = 299,
- SCALE_ = 300,
- SENSOR_ = 301,
- SIZE_ = 302,
- START_ = 303,
- STRETCH_ = 304,
- TITLES_ = 305,
- TYPE_ = 306,
- UNITS_ = 307,
- VALUE_ = 308,
- VALUES_ = 309,
- WAVELENGTH_ = 310
+ LIMITS_ = 286,
+ LINES_ = 287,
+ MAJOR_ = 288,
+ MAP_ = 289,
+ MINOR_ = 290,
+ NAMES_ = 291,
+ OFFSET_ = 292,
+ OFFSETS_ = 293,
+ ORDER_ = 294,
+ PIXEL_ = 295,
+ PIXELS_ = 296,
+ PLOT_ = 297,
+ PROJECTION_ = 298,
+ RANGE_ = 299,
+ REFLECTANCE_ = 300,
+ SAMPLES_ = 301,
+ SCALE_ = 302,
+ SCANNER_ = 303,
+ SENSOR_ = 304,
+ SIZE_ = 305,
+ START_ = 306,
+ STRETCH_ = 307,
+ TITLES_ = 308,
+ TYPE_ = 309,
+ UNITS_ = 310,
+ VALUE_ = 311,
+ VALUES_ = 312,
+ WAVELENGTH_ = 313
};
#endif
/* Tokens. */
@@ -123,31 +126,34 @@
#define INFO_ 283
#define IGNORE_ 284
#define INTERLEAVE_ 285
-#define LINES_ 286
-#define MAJOR_ 287
-#define MAP_ 288
-#define MINOR_ 289
-#define NAMES_ 290
-#define OFFSET_ 291
-#define OFFSETS_ 292
-#define ORDER_ 293
-#define PIXEL_ 294
-#define PLOT_ 295
-#define PROJECTION_ 296
-#define RANGE_ 297
-#define REFLECTANCE_ 298
-#define SAMPLES_ 299
-#define SCALE_ 300
-#define SENSOR_ 301
-#define SIZE_ 302
-#define START_ 303
-#define STRETCH_ 304
-#define TITLES_ 305
-#define TYPE_ 306
-#define UNITS_ 307
-#define VALUE_ 308
-#define VALUES_ 309
-#define WAVELENGTH_ 310
+#define LIMITS_ 286
+#define LINES_ 287
+#define MAJOR_ 288
+#define MAP_ 289
+#define MINOR_ 290
+#define NAMES_ 291
+#define OFFSET_ 292
+#define OFFSETS_ 293
+#define ORDER_ 294
+#define PIXEL_ 295
+#define PIXELS_ 296
+#define PLOT_ 297
+#define PROJECTION_ 298
+#define RANGE_ 299
+#define REFLECTANCE_ 300
+#define SAMPLES_ 301
+#define SCALE_ 302
+#define SCANNER_ 303
+#define SENSOR_ 304
+#define SIZE_ 305
+#define START_ 306
+#define STRETCH_ 307
+#define TITLES_ 308
+#define TYPE_ 309
+#define UNITS_ 310
+#define VALUE_ 311
+#define VALUES_ 312
+#define WAVELENGTH_ 313
@@ -162,7 +168,7 @@ typedef union YYSTYPE
char str[ENVIPARSERSIZE];
}
/* Line 1529 of yacc.c. */
-#line 166 "enviparser.H"
+#line 172 "enviparser.H"
YYSTYPE;
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
diff --git a/saotk/fitsy++/enviparser.Y b/saotk/fitsy++/enviparser.Y
index 13da876..341b7af 100644
--- a/saotk/fitsy++/enviparser.Y
+++ b/saotk/fitsy++/enviparser.Y
@@ -67,6 +67,7 @@ static float wave[MAXWAVES];
%token INFO_
%token IGNORE_
%token INTERLEAVE_
+%token LIMITS_
%token LINES_
%token MAJOR_
%token MAP_
@@ -76,12 +77,14 @@ static float wave[MAXWAVES];
%token OFFSETS_
%token ORDER_
%token PIXEL_
+%token PIXELS_
%token PLOT_
%token PROJECTION_
%token RANGE_
%token REFLECTANCE_
%token SAMPLES_
%token SCALE_
+%token SCANNER_
%token SENSOR_
%token SIZE_
%token START_
@@ -136,6 +139,7 @@ command : /* empty */
| BBL_ '=' liststr
| DATA_ GAIN_ VALUES_ '=' listnum
| DATA_ OFFSET_ VALUES_ '=' listnum
+ | SCANNER_ LIMITS_ '(' PIXELS_ ')' '=' INT INT
;
comment : ';' {DISCARD_(1)} STRING
@@ -253,6 +257,7 @@ listwave: '{' '}'
;
aWaves : aWaves ',' aWave
+ | aWaves ','
| aWave
;
diff --git a/saotk/fitsy++/file.C b/saotk/fitsy++/file.C
index ea7f73c..9188738 100644
--- a/saotk/fitsy++/file.C
+++ b/saotk/fitsy++/file.C
@@ -83,8 +83,6 @@ void envierror(FitsFile* envi, enviFlexLexer* ll, const char* m)
FitsFile::FitsFile()
{
- // cerr << "FitsFile()" << endl;
-
primary_ = NULL;
managePrimary_ = 0;
@@ -98,7 +96,7 @@ FitsFile::FitsFile()
ext_ = 0;
inherit_ = 0;
byteswap_ = lsb();
- orgFits_ = 1;
+ endian_ = BIG;
valid_ = 0;
pName_ = NULL;
@@ -114,78 +112,11 @@ FitsFile::FitsFile()
pWidth_ =0;
pHeight_ =0;
pDepth_ =1;
- pSize_ =0;
pSkip_ =0;
- pArch_ =NATIVE;
+ pArch_ =BIG;
pEncoding_ =RAW;
- pNRRDDimension_ = 0;
-
- pHPXOrder_ =-1;
- pHPXSystem_ =-1;
- pHPXLayout_ =-1;
- pHPXColumn_ =-1;
- pHPXQuad_ =-1;
-
- pCRPIX3_ =1;
- pCRVAL3_ =1;
- pCDELT3_ =1;
-
- coord_ =0;
- xvalid_ =0;
- xmin_ =0;
- xmax_ =0;
- yvalid_ =0;
- ymin_ =0;
- ymax_ =0;
- zvalid_ =0;
- zmin_ =0;
- zmax_ =0;
-}
-
-FitsFile::FitsFile(FitsFile* fits)
-{
- // cerr << "FitsFile(FitsFile* fits)" << endl;
-
- primary_ = NULL;
- managePrimary_ = 0;
-
- head_ = NULL;
- manageHead_ = 1;
-
- data_ = NULL;
-
- dataSize_ = 0;
- dataSkip_ = 0;
-
- ext_ = 0;
- inherit_ = 0;
- byteswap_ = lsb();
- orgFits_ = 1;
- valid_ = 0;
-
- pName_ = NULL;
- pExt_ = NULL;
- pIndex_ = -1;
-
- pFilter_ = NULL;
- pBinX_ = NULL;
- pBinY_ = NULL;
- pBinZ_ = NULL;
-
- pBitpix_ = fits->pBitpix();
- pWidth_ = fits->pWidth();
- pHeight_ = fits->pHeight();
- pDepth_ = fits->pDepth();
- pSize_ = fits->pSize();
- pSkip_ =0;
- pArch_ =NATIVE;
-
- pEncoding_ =RAW;
-
- pNRRDDimension_ = 0;
-
pHPXOrder_ =-1;
pHPXSystem_ =-1;
pHPXLayout_ =-1;
@@ -432,10 +363,7 @@ int FitsFile::validParams()
void FitsFile::setByteSwap()
{
- switch (pArch_) {
- case NATIVE:
- byteswap_ = 0;
- break;
+ switch (endian_) {
case BIG:
byteswap_ = lsb();
break;
diff --git a/saotk/fitsy++/file.h b/saotk/fitsy++/file.h
index 4444a0d..403bb0e 100644
--- a/saotk/fitsy++/file.h
+++ b/saotk/fitsy++/file.h
@@ -5,8 +5,6 @@
#ifndef __fitsfile_h__
#define __fitsfile_h__
-#include <tcl.h>
-
#include "head.h"
#define B4KB 4096
@@ -39,7 +37,7 @@ protected:
int ext_; // extension number
int inherit_; // do we have inheritence?
int byteswap_; // flag, true if byteswap is needed
- int orgFits_; // flag to indicate origin
+ ArchType endian_; // endian of data
int valid_; // flag, true if file is valid
char* pName_; // parsed file name
@@ -55,21 +53,17 @@ protected:
int pWidth_; // parsed width
int pHeight_; // parsed height
int pDepth_; // parsed depth
- size_t pSize_; // parsed size
size_t pSkip_; // parsed skip size
ArchType pArch_; // parsed arch type
+ EncodingType pEncoding_; // parsed encoding
- EncodingType pEncoding_;
-
- int pNRRDDimension_;
-
- int pHPXOrder_; // parsed HPX params
+ int pHPXOrder_; // parsed HPX params
int pHPXSystem_;
int pHPXLayout_;
int pHPXColumn_;
int pHPXQuad_;
- double pCRPIX3_;
+ double pCRPIX3_; // WCS_3 axis params
double pCRVAL3_;
double pCDELT3_;
@@ -94,7 +88,6 @@ protected:
public:
FitsFile();
- FitsFile(FitsFile*);
virtual ~FitsFile();
virtual void done() {}
@@ -109,13 +102,14 @@ public:
int ext() {return ext_;}
const char* extname() {return head_ ? head_->extname() : NULL;}
int inherit() {return inherit_;}
+ int setValid(int vv) {valid_=vv;}
int isValid() {return valid_;}
int isImage() {return head_ ? head_->isImage() : 0;}
int isTable() {return head_ ? head_->isTable() : 0;}
int isAsciiTable() {return head_ ? head_->isAsciiTable() : 0;}
int isBinTable() {return head_ ? head_->isBinTable() : 0;}
int byteswap() {return byteswap_;}
- int orgFits() {return orgFits_;}
+ ArchType endian() {return endian_;}
void setpName(const char*);
void setpExt(const char*);
@@ -142,7 +136,6 @@ public:
int pWidth() {return pWidth_;}
int pHeight() {return pHeight_;}
int pDepth() {return pDepth_;}
- size_t pSize() {return pSize_;}
size_t pSkip() {return pSkip_;}
ArchType pArch() {return pArch_;}
@@ -156,9 +149,6 @@ public:
EncodingType pEncoding() {return pEncoding_;}
void setpEncoding(EncodingType e) {pEncoding_ = e;}
- int pNRRDDimension() {return pNRRDDimension_;}
- void setpNRRDDimension(int d) {pNRRDDimension_ = d;}
-
int pHPXOrder() {return pHPXOrder_;}
int pHPXSystem() {return pHPXSystem_;}
int pHPXLayout() {return pHPXLayout_;}
diff --git a/saotk/fitsy++/hist.C b/saotk/fitsy++/hist.C
index 9faf7b5..1c4115d 100644
--- a/saotk/fitsy++/hist.C
+++ b/saotk/fitsy++/hist.C
@@ -521,15 +521,8 @@ FitsHistNext::FitsHistNext(FitsFile* prev)
ext_ = prev->ext();
inherit_ = prev->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
return;
}
diff --git a/saotk/fitsy++/hpx.C b/saotk/fitsy++/hpx.C
index 33b867d..f8c1792 100644
--- a/saotk/fitsy++/hpx.C
+++ b/saotk/fitsy++/hpx.C
@@ -564,38 +564,3 @@ void FitsHPX::swap()
dest[i] = u.f;
}
}
-
-FitsHPXNext::FitsHPXNext(FitsFile* prev)
-{
- primary_ = prev->primary();
- managePrimary_ = 0;
-
- head_ = prev->head();
- manageHead_ = 0;
-
- FitsImageHDU* hdu = (FitsImageHDU*)head_->hdu();
- data_ = (char*)prev->data() + hdu->imgbytes();
- dataSize_ = 0;
- dataSkip_ = 0;
-
- ext_ = prev->ext();
- inherit_ = prev->inherit();
- byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
- valid_ = 1;
-
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
- pHPXOrder_ = prev->pHPXColumn();
- pHPXSystem_ = prev->pHPXColumn();
- pHPXLayout_ = prev->pHPXColumn();
- pHPXColumn_ = prev->pHPXColumn();
- pHPXQuad_ = prev->pHPXQuad();
-
- return;
-}
diff --git a/saotk/fitsy++/hpx.h b/saotk/fitsy++/hpx.h
index 563d786..b53af4e 100644
--- a/saotk/fitsy++/hpx.h
+++ b/saotk/fitsy++/hpx.h
@@ -31,14 +31,12 @@ class FitsHPX : public FitsFile {
void NESTidx(int facet, int rotn, int jmap, long *healidx);
void RINGidx(int facet, int rotn, int jmap, long *healidx);
+ protected:
+ size_t pSize_;
+
public:
FitsHPX(FitsFile*, Order, CoordSys, Layout, int, int);
~FitsHPX();
};
-class FitsHPXNext : public FitsFile {
- public:
- FitsHPXNext(FitsFile* prev);
-};
-
#endif
diff --git a/saotk/fitsy++/map.C b/saotk/fitsy++/map.C
index 63f8cd1..0da9170 100644
--- a/saotk/fitsy++/map.C
+++ b/saotk/fitsy++/map.C
@@ -255,16 +255,9 @@ FitsFitsNextMap::FitsFitsNextMap(FitsFile* p)
ext_ = prev->ext();
inherit_ = prev->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
coord_ = prev->coord();
xvalid_ = prev->xvalid();
xmin_ = prev->xmin();
@@ -310,11 +303,11 @@ FitsArrMap::FitsArrMap()
return;
// do we byteswap?
+ endian_ = pArch_;
setByteSwap();
// made it this far, must be valid
valid_ = 1;
- orgFits_ = 0;
}
FitsNRRDMap::FitsNRRDMap()
@@ -367,10 +360,9 @@ FitsNRRDMap::FitsNRRDMap()
return;
// do we byteswap?
+ endian_ = pArch_;
setByteSwap();
- orgFits_ = 0;
-
// so far, so good
valid_ = 1;
}
diff --git a/saotk/fitsy++/mapincr.C b/saotk/fitsy++/mapincr.C
index 53dad6d..a133eb7 100644
--- a/saotk/fitsy++/mapincr.C
+++ b/saotk/fitsy++/mapincr.C
@@ -452,16 +452,9 @@ FitsFitsNextMapIncr::FitsFitsNextMapIncr(FitsFile* p)
ext_ = prev->ext();
inherit_ = prev->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
coord_ = prev->coord();
xvalid_ = prev->xvalid();
xmin_ = prev->xmin();
@@ -519,10 +512,10 @@ FitsArrMapIncr::FitsArrMapIncr()
dataSkip_ = pSkip_;
// do we byteswap?
+ endian_ = pArch_;
setByteSwap();
// made it this far, must be valid
- orgFits_ = 0;
valid_ = 1;
}
diff --git a/saotk/fitsy++/nrrd.C b/saotk/fitsy++/nrrd.C
index 8d372f5..cf1d021 100644
--- a/saotk/fitsy++/nrrd.C
+++ b/saotk/fitsy++/nrrd.C
@@ -5,11 +5,17 @@
#include "nrrd.h"
#include "head.h"
-FitsNRRD::FitsNRRD(FitsFile* fits) : FitsFile(fits)
+FitsNRRD::FitsNRRD(FitsFile* fits)
{
- pSize_ = (size_t)pWidth_*pHeight_*pDepth_;
- pSkip_ = 0;
- pArch_ = fits->pArch();
+ byteswap_ = fits->byteswap();
+ endian_ = fits->endian();
+
+ pBitpix_ = fits->pBitpix();
+ pWidth_ = fits->pWidth();
+ pHeight_ = fits->pHeight();
+ pDepth_ = fits->pDepth();
+
+ size_ = (size_t)pWidth_*pHeight_*pDepth_;
}
FitsNRRD::~FitsNRRD()
@@ -48,152 +54,23 @@ template <class T> void FitsNRRDm<T>::uncompress(FitsFile* fits)
if (!initHeader(fits))
return;
- T* dest = new T[pSize_];
+ T* dest = new T[size_];
if (!dest) {
internalError("Fitsy++ nrrd unable to allocate memory");
return;
}
- memset(dest, 0, pSize_*sizeof(T));
+ memset(dest, 0, size_*sizeof(T));
compressed(dest, (char*)fits->data(), fits->dataSize()-fits->dataSkip());
data_ = dest;
- dataSize_ = pSize_;
+ dataSize_ = size_;
dataSkip_ = 0;
- swapBytes(fits->pArch());
-
// all done
valid_ = 1;
}
-template<class T> void FitsNRRDm<T>::swapBytes(FitsFile::ArchType arch)
-{
- switch (arch) {
- case FitsFile::NATIVE:
- break;
- case FitsFile::BIG:
- if (!byteswap_) {
- T* dest = (T*)data_;
- for (int i=0; i<pSize_; i++)
- dest[i] = swap(dest+i);
- }
- break;
- case FitsFile::LITTLE:
- if (byteswap_) {
- T* dest = (T*)data_;
- for (int i=0; i<pSize_; i++)
- dest[i] = swap(dest+i);
- }
- break;
- }
-}
-
-template <> unsigned char FitsNRRDm<unsigned char>::swap(unsigned char* ptr)
-{
- return *ptr;
-}
-
-template <> short FitsNRRDm<short>::swap(short* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[2];
- short s;
- } u;
-
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.s;
-}
-
-template <> unsigned short FitsNRRDm<unsigned short>::swap(unsigned short* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[2];
- unsigned short s;
- } u;
-
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.s;
-}
-
-template <> int FitsNRRDm<int>::swap(int* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[4];
- int i;
- } u;
-
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.i;
-}
-
-template <> long long FitsNRRDm<long long>::swap(long long* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[8];
- long long i;
- } u;
-
- u.c[7] = *p++;
- u.c[6] = *p++;
- u.c[5] = *p++;
- u.c[4] = *p++;
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.i;
-}
-
-template <> float FitsNRRDm<float>::swap(float* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[4];
- float f;
- } u;
-
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.f;
-}
-
-template <> double FitsNRRDm<double>::swap(double* ptr)
-{
- const char* p = (const char*)ptr;
- union {
- char c[8];
- double d;
- } u;
-
- u.c[7] = *p++;
- u.c[6] = *p++;
- u.c[5] = *p++;
- u.c[4] = *p++;
- u.c[3] = *p++;
- u.c[2] = *p++;
- u.c[1] = *p++;
- u.c[0] = *p;
-
- return u.d;
-}
-
template class FitsNRRDm<unsigned char>;
template class FitsNRRDm<short>;
template class FitsNRRDm<unsigned short>;
@@ -201,37 +78,3 @@ template class FitsNRRDm<int>;
template class FitsNRRDm<long long>;
template class FitsNRRDm<float>;
template class FitsNRRDm<double>;
-
-FitsNRRDNext::FitsNRRDNext(FitsFile* p)
-{
- FitsNRRD* prev = (FitsNRRD*)p;
-
- primary_ = prev->primary();
- managePrimary_ = 0;
-
- head_ = prev->head();
- manageHead_ = 0;
-
- FitsImageHDU* hdu = (FitsImageHDU*)head_->hdu();
- data_ = (char*)prev->data() + hdu->imgbytes();
- dataSize_ = 0;
- dataSkip_ = 0;
-
- ext_ = prev->ext();
- inherit_ = prev->inherit();
- byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
- valid_ = 1;
-
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
- pEncoding_ = prev->pEncoding();
- pNRRDDimension_ = prev->pNRRDDimension();
-
- return;
-}
diff --git a/saotk/fitsy++/nrrd.h b/saotk/fitsy++/nrrd.h
index 6dc20ad..ee62525 100644
--- a/saotk/fitsy++/nrrd.h
+++ b/saotk/fitsy++/nrrd.h
@@ -9,6 +9,9 @@
class FitsNRRD : public FitsFile {
protected:
+ size_t size_;
+
+ protected:
int initHeader(FitsFile*);
public:
@@ -22,9 +25,6 @@ class FitsNRRDm : public FitsNRRD {
void swapBytes(FitsFile::ArchType);
protected:
- T swap(T* ptr);
-
- protected:
void uncompress(FitsFile* fits);
virtual int compressed(T*, char*, size_t) =0;
@@ -32,10 +32,5 @@ class FitsNRRDm : public FitsNRRD {
FitsNRRDm(FitsFile*);
};
-class FitsNRRDNext : public FitsFile {
-public:
- FitsNRRDNext(FitsFile* prev);
-};
-
#endif
diff --git a/saotk/fitsy++/nrrdgzip.C b/saotk/fitsy++/nrrdgzip.C
index 68a83e1..7e99466 100644
--- a/saotk/fitsy++/nrrdgzip.C
+++ b/saotk/fitsy++/nrrdgzip.C
@@ -27,7 +27,7 @@ template <class T> int FitsNRRDGzipm<T>::compressed(T* dest, char* src,
zstrm.opaque = NULL;
zstrm.avail_in = sz;
zstrm.next_in = (Bytef*)src;
- zstrm.avail_out = this->pSize_*sizeof(T);
+ zstrm.avail_out = this->size_*sizeof(T);
zstrm.next_out = (Bytef*)dest;
// look for both zlib and gzip headers
diff --git a/saotk/fitsy++/nrrdparser.C b/saotk/fitsy++/nrrdparser.C
index 6828661..4bd31a3 100644
--- a/saotk/fitsy++/nrrdparser.C
+++ b/saotk/fitsy++/nrrdparser.C
@@ -696,9 +696,9 @@ static const yytype_uint16 yyrline[] =
291, 292, 293, 294, 295, 298, 299, 300, 301, 302,
305, 306, 309, 310, 311, 312, 313, 314, 315, 316,
317, 320, 321, 324, 325, 328, 329, 332, 333, 336,
- 337, 340, 341, 344, 362, 363, 366, 367, 370, 371,
- 374, 375, 378, 379, 382, 383, 384, 387, 388, 391,
- 392, 395, 396
+ 337, 340, 341, 344, 361, 362, 365, 366, 369, 370,
+ 373, 374, 377, 378, 381, 382, 383, 386, 387, 390,
+ 391, 394, 395
};
#endif
@@ -1972,13 +1972,12 @@ yyreduce:
break;
}
dim++;
- nrrd->setpNRRDDimension(dim);
;}
break;
/* Line 1267 of yacc.c. */
-#line 1982 "nrrdparser.C"
+#line 1981 "nrrdparser.C"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2192,6 +2191,6 @@ yyreturn:
}
-#line 399 "nrrdparser.Y"
+#line 398 "nrrdparser.Y"
diff --git a/saotk/fitsy++/nrrdparser.Y b/saotk/fitsy++/nrrdparser.Y
index 9678990..a8672b3 100644
--- a/saotk/fitsy++/nrrdparser.Y
+++ b/saotk/fitsy++/nrrdparser.Y
@@ -355,7 +355,6 @@ size : INT
break;
}
dim++;
- nrrd->setpNRRDDimension(dim);
}
;
diff --git a/saotk/fitsy++/outchannel.C b/saotk/fitsy++/outchannel.C
index f5b248b..8351acd 100644
--- a/saotk/fitsy++/outchannel.C
+++ b/saotk/fitsy++/outchannel.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tcl.h>
+
#include "outchannel.h"
OutFitsChannel::OutFitsChannel(Tcl_Interp* interp, const char* ch)
diff --git a/saotk/fitsy++/outfile.C b/saotk/fitsy++/outfile.C
index 49f2f9d..b90e7a7 100644
--- a/saotk/fitsy++/outfile.C
+++ b/saotk/fitsy++/outfile.C
@@ -2,6 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <stdio.h>
#include "outfile.h"
OutFitsFile::OutFitsFile(const char* fn)
diff --git a/saotk/fitsy++/outfits.h b/saotk/fitsy++/outfits.h
index 1ead96d..d861050 100644
--- a/saotk/fitsy++/outfits.h
+++ b/saotk/fitsy++/outfits.h
@@ -5,8 +5,6 @@
#ifndef __outfits_h__
#define __outfits_h__
-#include <tcl.h>
-
#include "util.h"
#define B1KB 1024
diff --git a/saotk/fitsy++/parser.C b/saotk/fitsy++/parser.C
index 7fdd9f2..2b9bdef 100644
--- a/saotk/fitsy++/parser.C
+++ b/saotk/fitsy++/parser.C
@@ -436,7 +436,7 @@ union yyalloc
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 29
/* YYNRULES -- Number of rules. */
-#define YYNRULES 111
+#define YYNRULES 110
/* YYNRULES -- Number of states. */
#define YYNSTATES 188
@@ -494,11 +494,11 @@ static const yytype_uint16 yyprhs[] =
167, 171, 175, 179, 181, 185, 189, 193, 197, 199,
203, 207, 210, 212, 214, 216, 218, 224, 228, 236,
242, 246, 248, 252, 254, 258, 262, 266, 270, 274,
- 278, 282, 286, 290, 292, 293, 295, 297, 299, 301,
- 306, 308, 310, 312, 314, 316, 318, 320, 322, 324,
- 328, 334, 335, 338, 339, 341, 343, 347, 349, 353,
- 357, 361, 365, 369, 371, 373, 375, 377, 379, 381,
- 383, 385
+ 278, 282, 286, 290, 292, 294, 296, 298, 300, 305,
+ 307, 309, 311, 313, 315, 317, 319, 321, 323, 327,
+ 333, 334, 337, 338, 340, 342, 346, 348, 352, 356,
+ 360, 364, 368, 370, 372, 374, 376, 378, 380, 382,
+ 384
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
@@ -533,16 +533,16 @@ static const yytype_int8 yyrhs[] =
3, -1, 36, 45, 3, -1, 15, 45, 3, -1,
16, 45, 3, -1, 13, 45, 3, -1, 30, 45,
3, -1, 6, 45, 73, -1, 18, 45, 73, -1,
- 73, -1, -1, 8, -1, 9, -1, 23, -1, 24,
- -1, 75, 76, 77, 78, -1, 46, -1, 47, -1,
- 48, -1, 49, -1, 50, -1, 51, -1, 52, -1,
- 53, -1, 3, -1, 3, 54, 3, -1, 3, 54,
- 3, 54, 3, -1, -1, 43, 3, -1, -1, 50,
- -1, 46, -1, 79, 41, 80, -1, 80, -1, 32,
- 45, 81, -1, 27, 45, 82, -1, 22, 45, 83,
- -1, 14, 45, 3, -1, 28, 45, 3, -1, 19,
- -1, 20, -1, 17, -1, 33, -1, 29, -1, 25,
- -1, 19, -1, 26, -1, 31, -1
+ 73, -1, 8, -1, 9, -1, 23, -1, 24, -1,
+ 75, 76, 77, 78, -1, 46, -1, 47, -1, 48,
+ -1, 49, -1, 50, -1, 51, -1, 52, -1, 53,
+ -1, 3, -1, 3, 54, 3, -1, 3, 54, 3,
+ 54, 3, -1, -1, 43, 3, -1, -1, 50, -1,
+ 46, -1, 79, 41, 80, -1, 80, -1, 32, 45,
+ 81, -1, 27, 45, 82, -1, 22, 45, 83, -1,
+ 14, 45, 3, -1, 28, 45, 3, -1, 19, -1,
+ 20, -1, 17, -1, 33, -1, 29, -1, 25, -1,
+ 19, -1, 26, -1, 31, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
@@ -550,16 +550,16 @@ static const yytype_uint16 yyrline[] =
{
0, 82, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93, 94, 94, 95, 96, 97, 98,
- 98, 101, 102, 111, 112, 115, 116, 119, 121, 122,
- 123, 128, 134, 140, 149, 151, 156, 158, 163, 166,
- 168, 173, 175, 180, 183, 185, 190, 192, 197, 200,
- 202, 203, 206, 207, 208, 209, 212, 213, 214, 215,
- 216, 217, 220, 221, 224, 225, 226, 227, 228, 229,
- 230, 231, 232, 233, 236, 237, 238, 239, 240, 243,
- 246, 247, 248, 249, 250, 251, 252, 253, 256, 257,
- 258, 262, 263, 266, 267, 268, 271, 272, 275, 276,
- 277, 278, 279, 282, 283, 284, 285, 288, 289, 292,
- 293, 294
+ 98, 102, 103, 112, 113, 116, 117, 120, 122, 123,
+ 124, 129, 135, 141, 150, 152, 157, 159, 164, 167,
+ 169, 174, 176, 181, 184, 186, 191, 193, 198, 201,
+ 203, 204, 207, 208, 209, 210, 213, 214, 215, 216,
+ 217, 218, 221, 222, 225, 226, 227, 228, 229, 230,
+ 231, 232, 233, 234, 237, 238, 239, 240, 243, 246,
+ 247, 248, 249, 250, 251, 252, 253, 256, 257, 258,
+ 262, 263, 266, 267, 268, 271, 272, 275, 276, 277,
+ 278, 279, 282, 283, 284, 285, 288, 289, 292, 293,
+ 294
};
#endif
@@ -606,11 +606,11 @@ static const yytype_uint8 yyr1[] =
65, 65, 65, 65, 66, 66, 66, 66, 66, 67,
68, 68, 69, 69, 69, 69, 70, 70, 70, 70,
70, 70, 71, 71, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 73, 73, 73, 73, 73, 74,
- 75, 75, 75, 75, 75, 75, 75, 75, 76, 76,
- 76, 77, 77, 78, 78, 78, 79, 79, 80, 80,
- 80, 80, 80, 81, 81, 81, 81, 82, 82, 83,
- 83, 83
+ 72, 72, 72, 72, 73, 73, 73, 73, 74, 75,
+ 75, 75, 75, 75, 75, 75, 75, 76, 76, 76,
+ 77, 77, 78, 78, 78, 79, 79, 80, 80, 80,
+ 80, 80, 81, 81, 81, 81, 82, 82, 83, 83,
+ 83
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
@@ -623,11 +623,11 @@ static const yytype_uint8 yyr2[] =
3, 3, 3, 1, 3, 3, 3, 3, 1, 3,
3, 2, 1, 1, 1, 1, 5, 3, 7, 5,
3, 1, 3, 1, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 1, 0, 1, 1, 1, 1, 4,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
- 5, 0, 2, 0, 1, 1, 3, 1, 3, 3,
- 3, 3, 3, 1, 1, 1, 1, 1, 1, 1,
- 1, 1
+ 3, 3, 3, 1, 1, 1, 1, 1, 4, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 5,
+ 0, 2, 0, 1, 1, 3, 1, 3, 3, 3,
+ 3, 3, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -635,25 +635,25 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 19, 22, 0, 2, 0, 1, 74, 3, 9,
- 7, 20, 0, 0, 0, 14, 75, 76, 52, 53,
- 54, 0, 0, 0, 0, 0, 55, 0, 77, 78,
+ 0, 19, 22, 0, 2, 0, 1, 0, 3, 9,
+ 7, 20, 0, 0, 0, 14, 74, 75, 52, 53,
+ 54, 0, 0, 0, 0, 0, 55, 0, 76, 77,
0, 0, 0, 0, 0, 0, 0, 38, 0, 0,
- 0, 0, 0, 0, 63, 73, 0, 97, 0, 4,
- 5, 0, 8, 24, 26, 0, 0, 23, 25, 74,
- 0, 0, 0, 0, 0, 74, 0, 0, 0, 0,
+ 0, 0, 0, 0, 63, 73, 0, 96, 0, 4,
+ 5, 0, 8, 24, 26, 0, 0, 23, 25, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 49, 61, 0, 0, 51, 12, 74, 16, 0, 0,
- 6, 36, 37, 34, 35, 71, 0, 69, 101, 67,
- 68, 72, 109, 110, 111, 100, 108, 107, 99, 102,
- 70, 105, 103, 104, 106, 98, 64, 65, 66, 10,
+ 49, 61, 0, 0, 51, 12, 0, 16, 0, 0,
+ 6, 36, 37, 34, 35, 71, 0, 69, 100, 67,
+ 68, 72, 108, 109, 110, 99, 107, 106, 98, 101,
+ 70, 104, 102, 103, 105, 97, 64, 65, 66, 10,
11, 18, 0, 43, 28, 0, 0, 50, 13, 62,
- 17, 96, 0, 80, 81, 82, 83, 84, 85, 86,
- 87, 0, 0, 0, 0, 0, 57, 60, 0, 30,
- 32, 0, 88, 91, 41, 42, 39, 40, 0, 48,
- 29, 0, 0, 0, 15, 0, 0, 93, 0, 0,
- 59, 56, 0, 31, 33, 89, 92, 95, 94, 79,
- 46, 47, 44, 45, 0, 0, 58, 90
+ 17, 95, 0, 79, 80, 81, 82, 83, 84, 85,
+ 86, 0, 0, 0, 0, 0, 57, 60, 0, 30,
+ 32, 0, 87, 90, 41, 42, 39, 40, 0, 48,
+ 29, 0, 0, 0, 15, 0, 0, 92, 0, 0,
+ 59, 56, 0, 31, 33, 88, 91, 94, 93, 78,
+ 46, 47, 44, 45, 0, 0, 58, 89
};
/* YYDEFGOTO[NTERM-NUM]. */
@@ -1615,37 +1615,37 @@ yyreduce:
break;
case 20:
-#line 98 "parser.Y"
- {ff->setpFilter(ff_filter);;}
+#line 99 "parser.Y"
+ {ff->setValid(1); ff->setpFilter(ff_filter);;}
break;
case 22:
-#line 102 "parser.Y"
+#line 103 "parser.Y"
{ff->setpName((yyvsp[(1) - (1)].str));;}
break;
case 23:
-#line 111 "parser.Y"
+#line 112 "parser.Y"
{ff->setpExt((yyvsp[(2) - (3)].str));;}
break;
case 24:
-#line 112 "parser.Y"
+#line 113 "parser.Y"
{ff->setpIndex((yyvsp[(2) - (3)].integer));;}
break;
case 25:
-#line 115 "parser.Y"
+#line 116 "parser.Y"
{ff->setpExt((yyvsp[(1) - (2)].str));;}
break;
case 26:
-#line 116 "parser.Y"
+#line 117 "parser.Y"
{ff->setpIndex((yyvsp[(1) - (2)].integer));;}
break;
case 30:
-#line 124 "parser.Y"
+#line 125 "parser.Y"
{
ff->setXMin((yyvsp[(3) - (5)].integer)-(yyvsp[(1) - (5)].integer)/2); ff->setXMax((yyvsp[(3) - (5)].integer)+(yyvsp[(1) - (5)].integer)/2); ff->setXValid(1);
ff->setYMin((yyvsp[(5) - (5)].integer)-(yyvsp[(1) - (5)].integer)/2); ff->setYMax((yyvsp[(5) - (5)].integer)+(yyvsp[(1) - (5)].integer)/2); ff->setYValid(1);
@@ -1653,7 +1653,7 @@ yyreduce:
break;
case 31:
-#line 129 "parser.Y"
+#line 130 "parser.Y"
{
ff->setXMin((yyvsp[(3) - (7)].integer)-(yyvsp[(1) - (7)].integer)/2); ff->setXMax((yyvsp[(3) - (7)].integer)+(yyvsp[(1) - (7)].integer)/2); ff->setXValid(1);
ff->setYMin((yyvsp[(5) - (7)].integer)-(yyvsp[(1) - (7)].integer)/2); ff->setYMax((yyvsp[(5) - (7)].integer)+(yyvsp[(1) - (7)].integer)/2); ff->setYValid(1);
@@ -1662,7 +1662,7 @@ yyreduce:
break;
case 32:
-#line 135 "parser.Y"
+#line 136 "parser.Y"
{
ff->setXMin((yyvsp[(3) - (5)].integer)-(yyvsp[(1) - (5)].integer)/2); ff->setXMax((yyvsp[(3) - (5)].integer)+(yyvsp[(1) - (5)].integer)/2); ff->setXValid(1);
ff->setYMin((yyvsp[(5) - (5)].integer)-(yyvsp[(1) - (5)].integer)/2); ff->setYMax((yyvsp[(5) - (5)].integer)+(yyvsp[(1) - (5)].integer)/2); ff->setYValid(1);
@@ -1671,7 +1671,7 @@ yyreduce:
break;
case 33:
-#line 141 "parser.Y"
+#line 142 "parser.Y"
{
ff->setXMin((yyvsp[(3) - (7)].integer)-(yyvsp[(1) - (7)].integer)/2); ff->setXMax((yyvsp[(3) - (7)].integer)+(yyvsp[(1) - (7)].integer)/2); ff->setXValid(1);
ff->setYMin((yyvsp[(5) - (7)].integer)-(yyvsp[(1) - (7)].integer)/2); ff->setYMax((yyvsp[(5) - (7)].integer)+(yyvsp[(1) - (7)].integer)/2); ff->setYValid(1);
@@ -1681,12 +1681,12 @@ yyreduce:
break;
case 34:
-#line 150 "parser.Y"
+#line 151 "parser.Y"
{ff->setXMin((yyvsp[(1) - (3)].integer)); ff->setXMax((yyvsp[(3) - (3)].integer)); ff->setXValid(1);;}
break;
case 35:
-#line 152 "parser.Y"
+#line 153 "parser.Y"
{
ff->setXMin((yyvsp[(1) - (3)].integer)); ff->setXMax((yyvsp[(3) - (3)].integer)); ff->setXValid(1);
ff->setCoord(1);
@@ -1694,12 +1694,12 @@ yyreduce:
break;
case 36:
-#line 157 "parser.Y"
+#line 158 "parser.Y"
{ff->setXMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setXMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setXValid(1);;}
break;
case 37:
-#line 159 "parser.Y"
+#line 160 "parser.Y"
{
ff->setXMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setXMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setXValid(1);
ff->setCoord(1);
@@ -1707,17 +1707,17 @@ yyreduce:
break;
case 38:
-#line 163 "parser.Y"
+#line 164 "parser.Y"
{ff->setXValid(0);;}
break;
case 39:
-#line 167 "parser.Y"
+#line 168 "parser.Y"
{ff->setYMin((yyvsp[(1) - (3)].integer)); ff->setYMax((yyvsp[(3) - (3)].integer)); ff->setYValid(1);;}
break;
case 40:
-#line 169 "parser.Y"
+#line 170 "parser.Y"
{
ff->setYMin((yyvsp[(1) - (3)].integer)); ff->setYMax((yyvsp[(3) - (3)].integer)); ff->setYValid(1);
ff->setCoord(1);
@@ -1725,12 +1725,12 @@ yyreduce:
break;
case 41:
-#line 174 "parser.Y"
+#line 175 "parser.Y"
{ff->setYMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setYMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setYValid(1);;}
break;
case 42:
-#line 176 "parser.Y"
+#line 177 "parser.Y"
{
ff->setYMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setYMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setYValid(1);
ff->setCoord(1);
@@ -1738,17 +1738,17 @@ yyreduce:
break;
case 43:
-#line 180 "parser.Y"
+#line 181 "parser.Y"
{ff->setYValid(0);;}
break;
case 44:
-#line 184 "parser.Y"
+#line 185 "parser.Y"
{ff->setZMin((yyvsp[(1) - (3)].integer)); ff->setZMax((yyvsp[(3) - (3)].integer)); ff->setZValid(1);;}
break;
case 45:
-#line 186 "parser.Y"
+#line 187 "parser.Y"
{
ff->setZMin((yyvsp[(1) - (3)].integer)); ff->setZMax((yyvsp[(3) - (3)].integer)); ff->setZValid(1);
ff->setCoord(1);
@@ -1756,12 +1756,12 @@ yyreduce:
break;
case 46:
-#line 191 "parser.Y"
+#line 192 "parser.Y"
{ff->setZMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setZMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setZValid(1);;}
break;
case 47:
-#line 193 "parser.Y"
+#line 194 "parser.Y"
{
ff->setZMin((yyvsp[(3) - (3)].integer)-(yyvsp[(1) - (3)].integer)/2); ff->setZMax((yyvsp[(3) - (3)].integer)+(yyvsp[(1) - (3)].integer)/2); ff->setZValid(1);
ff->setCoord(1);
@@ -1769,243 +1769,238 @@ yyreduce:
break;
case 48:
-#line 197 "parser.Y"
+#line 198 "parser.Y"
{ff->setZValid(0);;}
break;
case 56:
-#line 212 "parser.Y"
+#line 213 "parser.Y"
{ff->setpBinXY((yyvsp[(2) - (5)].str),(yyvsp[(4) - (5)].str));;}
break;
case 57:
-#line 213 "parser.Y"
+#line 214 "parser.Y"
{ff->setpBinXY((yyvsp[(1) - (3)].str),(yyvsp[(3) - (3)].str));;}
break;
case 58:
-#line 214 "parser.Y"
+#line 215 "parser.Y"
{ff->setpBinXYZ((yyvsp[(2) - (7)].str),(yyvsp[(4) - (7)].str),(yyvsp[(6) - (7)].str));;}
break;
case 59:
-#line 215 "parser.Y"
+#line 216 "parser.Y"
{ff->setpBinXYZ((yyvsp[(1) - (5)].str),(yyvsp[(3) - (5)].str),(yyvsp[(5) - (5)].str));;}
break;
case 60:
-#line 216 "parser.Y"
+#line 217 "parser.Y"
{ff->setpBinZ((yyvsp[(2) - (3)].str));;}
break;
case 61:
-#line 217 "parser.Y"
+#line 218 "parser.Y"
{ff->setpBinZ((yyvsp[(1) - (1)].str));;}
break;
case 64:
-#line 224 "parser.Y"
+#line 225 "parser.Y"
{ff->setpWidth((yyvsp[(3) - (3)].integer));;}
break;
case 65:
-#line 225 "parser.Y"
+#line 226 "parser.Y"
{ff->setpHeight((yyvsp[(3) - (3)].integer));;}
break;
case 66:
-#line 226 "parser.Y"
+#line 227 "parser.Y"
{ff->setpDepth((yyvsp[(3) - (3)].integer));;}
break;
case 67:
-#line 227 "parser.Y"
+#line 228 "parser.Y"
{ff->setpWidth((yyvsp[(3) - (3)].integer));ff->setpHeight((yyvsp[(3) - (3)].integer));;}
break;
case 68:
-#line 228 "parser.Y"
+#line 229 "parser.Y"
{ff->setpWidth((yyvsp[(3) - (3)].integer));ff->setpHeight((yyvsp[(3) - (3)].integer));;}
break;
case 69:
-#line 229 "parser.Y"
+#line 230 "parser.Y"
{ff->setpBitpix((yyvsp[(3) - (3)].integer));;}
break;
case 70:
-#line 230 "parser.Y"
+#line 231 "parser.Y"
{ff->setpSkip((yyvsp[(3) - (3)].integer));;}
break;
case 71:
-#line 231 "parser.Y"
+#line 232 "parser.Y"
{ff->setpArch((FitsFile::ArchType)(yyvsp[(3) - (3)].integer));;}
break;
case 72:
-#line 232 "parser.Y"
+#line 233 "parser.Y"
{ff->setpArch((FitsFile::ArchType)(yyvsp[(3) - (3)].integer));;}
break;
case 73:
-#line 233 "parser.Y"
+#line 234 "parser.Y"
{ff->setpArch((FitsFile::ArchType)(yyvsp[(1) - (1)].integer));;}
break;
case 74:
-#line 236 "parser.Y"
- {(yyval.integer) = FitsFile::BIG;;}
- break;
-
- case 75:
#line 237 "parser.Y"
{(yyval.integer) = FitsFile::BIG;;}
break;
- case 76:
+ case 75:
#line 238 "parser.Y"
{(yyval.integer) = FitsFile::BIG;;}
break;
- case 77:
+ case 76:
#line 239 "parser.Y"
{(yyval.integer) = FitsFile::LITTLE;;}
break;
- case 78:
+ case 77:
#line 240 "parser.Y"
{(yyval.integer) = FitsFile::LITTLE;;}
break;
- case 80:
+ case 79:
#line 246 "parser.Y"
{ff->setpBitpix(8);;}
break;
- case 81:
+ case 80:
#line 247 "parser.Y"
{ff->setpBitpix(16);;}
break;
- case 82:
+ case 81:
#line 248 "parser.Y"
{ff->setpBitpix(-16);;}
break;
- case 83:
+ case 82:
#line 249 "parser.Y"
{ff->setpBitpix(32);;}
break;
- case 84:
+ case 83:
#line 250 "parser.Y"
{ff->setpBitpix(64);;}
break;
- case 85:
+ case 84:
#line 251 "parser.Y"
{ff->setpBitpix(-32);;}
break;
- case 86:
+ case 85:
#line 252 "parser.Y"
{ff->setpBitpix(-32);;}
break;
- case 87:
+ case 86:
#line 253 "parser.Y"
{ff->setpBitpix(-64);;}
break;
- case 88:
+ case 87:
#line 256 "parser.Y"
{ff->setpWidth((yyvsp[(1) - (1)].integer));ff->setpHeight((yyvsp[(1) - (1)].integer));;}
break;
- case 89:
+ case 88:
#line 257 "parser.Y"
{ff->setpWidth((yyvsp[(1) - (3)].integer));ff->setpHeight((yyvsp[(3) - (3)].integer));;}
break;
- case 90:
+ case 89:
#line 259 "parser.Y"
{ff->setpWidth((yyvsp[(1) - (5)].integer));ff->setpHeight((yyvsp[(3) - (5)].integer));ff->setpDepth((yyvsp[(5) - (5)].integer));;}
break;
- case 92:
+ case 91:
#line 263 "parser.Y"
{ff->setpSkip((yyvsp[(2) - (2)].integer));;}
break;
- case 94:
+ case 93:
#line 267 "parser.Y"
{ff->setpArch(FitsFile::LITTLE);;}
break;
- case 95:
+ case 94:
#line 268 "parser.Y"
{ff->setpArch(FitsFile::BIG);;}
break;
- case 101:
+ case 100:
#line 278 "parser.Y"
{ff->setpHPXColumn((yyvsp[(3) - (3)].integer));;}
break;
- case 102:
+ case 101:
#line 279 "parser.Y"
{ff->setpHPXQuad((yyvsp[(3) - (3)].integer));;}
break;
- case 103:
+ case 102:
#line 282 "parser.Y"
{ff->setpHPXSystem(FitsHPX::EQU);;}
break;
- case 104:
+ case 103:
#line 283 "parser.Y"
{ff->setpHPXSystem(FitsHPX::GAL);;}
break;
- case 105:
+ case 104:
#line 284 "parser.Y"
{ff->setpHPXSystem(FitsHPX::ECL);;}
break;
- case 106:
+ case 105:
#line 285 "parser.Y"
{ff->setpHPXSystem(FitsHPX::UNKNOWN);;}
break;
- case 107:
+ case 106:
#line 288 "parser.Y"
{ff->setpHPXOrder(FitsHPX::RING);;}
break;
- case 108:
+ case 107:
#line 289 "parser.Y"
{ff->setpHPXOrder(FitsHPX::NESTED);;}
break;
- case 109:
+ case 108:
#line 292 "parser.Y"
{ff->setpHPXLayout(FitsHPX::EQUATOR);;}
break;
- case 110:
+ case 109:
#line 293 "parser.Y"
{ff->setpHPXLayout(FitsHPX::NORTH);;}
break;
- case 111:
+ case 110:
#line 294 "parser.Y"
{ff->setpHPXLayout(FitsHPX::SOUTH);;}
break;
/* Line 1267 of yacc.c. */
-#line 2009 "parser.C"
+#line 2004 "parser.C"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
diff --git a/saotk/fitsy++/parser.Y b/saotk/fitsy++/parser.Y
index 91171d8..70f6d43 100644
--- a/saotk/fitsy++/parser.Y
+++ b/saotk/fitsy++/parser.Y
@@ -95,7 +95,8 @@ command : filename
| filename '[' hpxs ']'
| filename '[' hpxs ']' sect
| filename '[' extb hpxs ']'
- | error {GOTOFILT(0)} STRING {ff->setpFilter(ff_filter);}
+ | error {GOTOFILT(0)} STRING
+ {ff->setValid(1); ff->setpFilter(ff_filter);}
;
filename : /* empty */
@@ -233,8 +234,7 @@ arr : XDIM_ '=' INT {ff->setpWidth($3);}
| endian {ff->setpArch((FitsFile::ArchType)$1);}
;
-endian : /* empty */ {$$ = FitsFile::BIG;}
- | BIG_ {$$ = FitsFile::BIG;}
+endian : BIG_ {$$ = FitsFile::BIG;}
| BIGENDIAN_ {$$ = FitsFile::BIG;}
| LITTLE_ {$$ = FitsFile::LITTLE;}
| LITTLEENDIAN_ {$$ = FitsFile::LITTLE;}
diff --git a/saotk/fitsy++/photo.C b/saotk/fitsy++/photo.C
index 3ca380e..9e20c9d 100644
--- a/saotk/fitsy++/photo.C
+++ b/saotk/fitsy++/photo.C
@@ -7,6 +7,8 @@
#include <iomanip>
using namespace std;
+#include <tk.h>
+
#include "photo.h"
FitsPhoto::FitsPhoto(Tcl_Interp* interp, const char* ph)
@@ -60,8 +62,8 @@ FitsPhoto::FitsPhoto(Tcl_Interp* interp, const char* ph)
// made it this far, must be valid
byteswap_ = 0;
+ endian_ = lsb() ? LITTLE : BIG;
valid_ = 1;
- orgFits_ = 0;
}
FitsPhoto::~FitsPhoto()
@@ -118,8 +120,8 @@ FitsPhotoCube::FitsPhotoCube(Tcl_Interp* interp, const char* ph)
// made it this far, must be valid
byteswap_ = 0;
+ endian_ = lsb() ? LITTLE : BIG;
valid_ = 1;
- orgFits_ = 0;
}
FitsPhotoCube::~FitsPhotoCube()
@@ -144,15 +146,8 @@ FitsPhotoCubeNext::FitsPhotoCubeNext(FitsFile* prev)
ext_ = prev->ext();
inherit_ = head_->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
return;
}
diff --git a/saotk/fitsy++/photo.h b/saotk/fitsy++/photo.h
index 95df744..eee2d66 100644
--- a/saotk/fitsy++/photo.h
+++ b/saotk/fitsy++/photo.h
@@ -5,6 +5,8 @@
#ifndef __fitsphoto_h__
#define __fitsphoto_h__
+#include <tcl.h>
+
#include "vector.h"
#include "file.h"
diff --git a/saotk/fitsy++/savefits.C b/saotk/fitsy++/savefits.C
index 9d87000..bc17c44 100644
--- a/saotk/fitsy++/savefits.C
+++ b/saotk/fitsy++/savefits.C
@@ -7,6 +7,8 @@
#include <iomanip>
using namespace std;
+#include <tcl.h>
+
#include "file.h"
#include "outfile.h"
#include "outchannel.h"
@@ -225,23 +227,13 @@ int FitsFile::saveFits(OutFitsStream& str)
{
FitsImageHDU* hdu = (FitsImageHDU*)(head()->hdu());
- if (orgFits_)
+ switch (endian_) {
+ case BIG:
str.write((char*)data(), hdu->imgbytes());
- else {
- switch (pArch_) {
- case NATIVE:
- if (!lsb())
- str.write((char*)data(), hdu->imgbytes());
- else
- str.writeSwap((char*)data(), hdu->imgbytes(), head()->bitpix());
- break;
- case BIG:
- str.write((char*)data(), hdu->imgbytes());
- break;
- case LITTLE:
- str.writeSwap((char*)data(), hdu->imgbytes(), head()->bitpix());
- break;
- }
+ break;
+ case LITTLE:
+ str.writeSwap((char*)data(), hdu->imgbytes(), head()->bitpix());
+ break;
}
return hdu->imgbytes();
@@ -277,23 +269,13 @@ int FitsFile::saveFitsTable(OutFitsStream& str)
// our data may be short (mmap or bad fits), so write valid data
// then write the pad, becareful with arch, if array
- if (orgFits_)
+ switch (endian_) {
+ case BIG:
str.write((char*)data(), head()->allbytes());
- else {
- switch (pArch_) {
- case NATIVE:
- if (!lsb())
- str.write((char*)data(), head()->allbytes());
- else
- str.writeSwap((char*)data(), head()->allbytes(), head()->bitpix());
- break;
- case BIG:
- str.write((char*)data(), head()->allbytes());
- break;
- case LITTLE:
- str.writeSwap((char*)data(), head()->allbytes(), head()->bitpix());
- break;
- }
+ break;
+ case LITTLE:
+ str.writeSwap((char*)data(), head()->allbytes(), head()->bitpix());
+ break;
}
cnt += head()->allbytes();
@@ -367,59 +349,16 @@ int FitsFile::saveFitsIIS(OutFitsStream& str, Vector& iisz)
return size*sizeof(float);
}
-int FitsFile::saveArray(OutFitsStream& str, ArchType endian)
+int FitsFile::saveArray(OutFitsStream& str, ArchType which)
{
// only save one slice
size_t size = head_->naxis(0)*head_->naxis(1)*abs(head_->bitpix()/8);
int bitpix = head_->bitpix();
- switch (endian) {
- case NATIVE:
- case BIG:
- {
- if (orgFits_)
- str.write((char*)data(), size);
- else {
- switch (pArch_) {
- case NATIVE:
- if (!lsb())
- str.write((char*)data(), size);
- else
- str.writeSwap((char*)data(), size, bitpix);
- break;
- case BIG:
- str.write((char*)data(), size);
- break;
- case LITTLE:
- str.writeSwap((char*)data(), size, bitpix);
- break;
- }
- }
- }
- break;
- case LITTLE:
- {
- if (orgFits_)
- str.writeSwap((char*)data(), size, bitpix);
- else {
- switch (pArch_) {
- case NATIVE:
- if (!lsb())
- str.writeSwap((char*)data(), size, bitpix);
- else
- str.write((char*)data(), size);
- break;
- case BIG:
- str.writeSwap((char*)data(), size, bitpix);
- break;
- case LITTLE:
- str.write((char*)data(), size);
- break;
- }
- }
- }
- break;
- }
+ if (which == endian_)
+ str.write((char*)data(), size);
+ else
+ str.writeSwap((char*)data(), size, bitpix);
return size;
}
diff --git a/saotk/fitsy++/smap.C b/saotk/fitsy++/smap.C
index f2e93b6..5a0e3ea 100644
--- a/saotk/fitsy++/smap.C
+++ b/saotk/fitsy++/smap.C
@@ -139,10 +139,9 @@ FitsENVISMap::FitsENVISMap()
}
// do we byteswap?
+ endian_ = pArch_;
setByteSwap();
- orgFits_ = 0;
-
// so far, so good
valid_ = 1;
}
@@ -165,16 +164,9 @@ FitsFitsNextSMap::FitsFitsNextSMap(FitsFile* p)
ext_ = prev->ext();
inherit_ = prev->inherit();
byteswap_ = prev->byteswap();
- orgFits_ = prev->orgFits();
+ endian_ = prev->endian();
valid_ = 1;
- pWidth_ = prev->pWidth();
- pHeight_ = prev->pHeight();
- pDepth_ = prev->pDepth();
- pBitpix_ = prev->pBitpix();
- pSkip_ = prev->pSkip();
- pArch_ = prev->pArch();
-
coord_ = prev->coord();
xvalid_ = prev->xvalid();
xmin_ = prev->xmin();
diff --git a/saotk/fitsy++/strm.C b/saotk/fitsy++/strm.C
index 3bc72b2..7dbfa1a 100644
--- a/saotk/fitsy++/strm.C
+++ b/saotk/fitsy++/strm.C
@@ -6,6 +6,8 @@
#include <stdio.h>
#include <sys/socket.h>
+#include <tcl.h>
+
#include "strm.h"
#include "util.h"
@@ -566,16 +568,9 @@ template<class T> FitsFitsNextStream<T>::FitsFitsNextStream(FitsFile* p)
this->ext_ = prev->ext();
this->inherit_ = prev->inherit();
this->byteswap_ = prev->byteswap();
- this->orgFits_ = prev->orgFits();
+ this->endian_ = prev->endian();
this->valid_ = 1;
- this->pWidth_ = prev->pWidth();
- this->pHeight_ = prev->pHeight();
- this->pDepth_ = prev->pDepth();
- this->pBitpix_ = prev->pBitpix();
- this->pSkip_ = prev->pSkip();
- this->pArch_ = prev->pArch();
-
this->coord_ = prev->coord();
this->xvalid_ = prev->xvalid();
this->xmin_ = prev->xmin();
@@ -632,11 +627,11 @@ template<class T> FitsArrStream<T>::FitsArrStream(FitsFile::FlushMode f)
}
// do we need to byteswap?
+ this->endian_ = this->pArch_;
this->setByteSwap();
// made it this far, must be good
this->valid_ = 1;
- this->orgFits_ = 0;
if (this->flush_ == this->FLUSH)
this->skipEnd();
@@ -693,11 +688,11 @@ template<class T> FitsNRRDStream<T>::FitsNRRDStream(FitsFile::FlushMode f)
}
// do we need to byteswap?
+ this->endian_ = this->pArch_;
this->setByteSwap();
// made it this far, must be good
this->valid_ = 1;
- this->orgFits_ = 0;
if (this->flush_ == this->FLUSH)
this->skipEnd();
diff --git a/saotk/fitsy++/var.C b/saotk/fitsy++/var.C
index 64d7273..82b1386 100644
--- a/saotk/fitsy++/var.C
+++ b/saotk/fitsy++/var.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tcl.h>
+
#include "var.h"
FitsVar::FitsVar(Tcl_Interp* interp, const char* var, const char* fn)
diff --git a/saotk/frame/Makefile b/saotk/frame/Makefile
index ade9fe0..a054bf7 100644
--- a/saotk/frame/Makefile
+++ b/saotk/frame/Makefile
@@ -8,7 +8,7 @@ CXXFLAGS = $(CXXOPT) -w \
-I/usr/include/libxml2 \
-I../../$(ASTDIR)
-SS = \
+SRC = \
annulus.C \
base.C \
basecommand.C \
@@ -91,17 +91,7 @@ SS = \
segment.C \
tag.C \
text.C \
- vect.C
-
-ifeq ($(OS),unix)
-SSP = \
- colorscalepseudo8.C \
- framepseudo.C \
- framepseudocolor.C \
- framepseudocolor8.C
-endif
-
-SRC = $(SS) $(SSP) \
+ vect.C \
ciaoparser.C \
ciaolex.C \
ds9parser.C \
@@ -120,20 +110,13 @@ SRC = $(SS) $(SSP) \
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o parser.output ds9parser.output ciaoparser.output prosparser.output tngparser.output saoparser.output xyparser.output
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o parser.output ds9parser.output ciaoparser.output prosparser.output tngparser.output saoparser.output xyparser.output
parsers : ciaoparser ds9parser parser prosparser saoparser tngparser xyparser
@@ -166,12 +149,3 @@ xyparser : FORCE
flex -Pxy -oxylex.C xylex.L
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SS:.C=.d)
-endif
diff --git a/saotk/frame/annulus.C b/saotk/frame/annulus.C
index b447921..8f90673 100644
--- a/saotk/frame/annulus.C
+++ b/saotk/frame/annulus.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "annulus.h"
#include "fitsimage.h"
diff --git a/saotk/frame/base.C b/saotk/frame/base.C
index d8d77b2..69777df 100644
--- a/saotk/frame/base.C
+++ b/saotk/frame/base.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -2163,7 +2163,7 @@ void Base::macosxCrosshair()
if (!useCrosshair)
return;
- Vector rr = mapFromRef(crosshair,WIDGET);
+ Vector rr = mapFromRef(crosshair,Coord::WIDGET);
Vector aa = Vector(rr[0],1) * widgetToCanvas;
Vector bb = Vector(rr[0],options->height) * widgetToCanvas;
Vector cc = Vector(1,rr[1]) * widgetToCanvas;
diff --git a/saotk/frame/base.h b/saotk/frame/base.h
index f79df88..b7c3563 100644
--- a/saotk/frame/base.h
+++ b/saotk/frame/base.h
@@ -120,7 +120,7 @@ public:
enum UpdateType {MATRIX, BASE, PIXMAP, NOUPDATE};
enum MemType {ALLOC, ALLOCGZ, CHANNEL, MMAP, SMMAP, MMAPINCR,
- SHARE, SSHARE, SOCKET, SOCKETGZ, VAR, HIST, COMPRESS, PHOTO};
+ SHARE, SSHARE, SOCKET, SOCKETGZ, VAR, HIST, POST, PHOTO};
enum MosaicType {NOMOSAIC, IRAF, WCSMOSAIC, WFPC2};
enum LayerType {IMG, MASK};
enum LoadMethod {LOADALL, INCR};
@@ -516,7 +516,7 @@ public:
void macosxContours();
void macosxCrosshair();
virtual void macosxGraphics() {}
- void macosxImage(float, int, int, const Vector&, const Vector&)
+ void macosxImage(float, int, int, const Vector&, const Vector&);
void macosxMarkers(List<Marker>* ml);
#endif
#ifdef _GWIN32
diff --git a/saotk/frame/basebox.C b/saotk/frame/basebox.C
index 59a241d..4845e98 100644
--- a/saotk/frame/basebox.C
+++ b/saotk/frame/basebox.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "basebox.h"
#include "fitsimage.h"
@@ -81,7 +83,7 @@ void BaseBox::renderMACOSX()
for (int ii=0; ii<numAnnuli_; ii++) {
Vector vv[numPoints_];
for (int jj=0; jj<numPoints_; jj++)
- vv[jj] = parent->mapFromRef(vertices_[ii][jj],CANVAS);
+ vv[jj] = parent->mapFromRef(vertices_[ii][jj],Coord::CANVAS);
macosxDrawLines(vv, numPoints_);
}
deleteVertices();
@@ -135,7 +137,8 @@ void BaseBox::updateHandles()
handle[ii+4] = fwdMap(Vector((annuli_[ii][0])/2.,0),Coord::CANVAS);
}
-int BaseBox::isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
+
+int BaseBox::isInRef(const Vector& vv, int nn)
{
// during resize, annuli_ can be negative
Vector ss = annuli_[nn].abs();
@@ -144,8 +147,7 @@ int BaseBox::isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
if (!ss[0] || !ss[1])
return 0;
- Vector pp = bckMap(vv,sys);
-
+ Vector pp = (Vector&)vv;
if (pp[0]<-ss[0]/2 || pp[0]>=ss[0]/2 || pp[1]<=-ss[1]/2 || pp[1]>ss[1]/2)
return 0;
else
diff --git a/saotk/frame/basebox.h b/saotk/frame/basebox.h
index 9c5d12c..18c7184 100644
--- a/saotk/frame/basebox.h
+++ b/saotk/frame/basebox.h
@@ -23,6 +23,8 @@ class BaseBox : public BaseMarker {
void vertBPrep(double a1, double a2, double ll, double ul, int ii, int* cnt);
void vertBSeg(double ang1, double ang2, int ii, int* cnt);
+ int isInRef(const Vector& vv, int);
+
protected:
virtual void updateHandles();
Vector intersect(Vector, double);
@@ -52,7 +54,14 @@ public:
{return isIn(vv, Coord::CANVAS);}
int isIn(const Vector& vv, Coord::InternalSystem sys)
{return isIn(vv,sys,numAnnuli_-1);}
- int isIn(const Vector&, Coord::InternalSystem, int);
+ int isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
+ {return isInRef(bckMap(vv,sys),nn);}
+
+ // valid for non-fixed only
+ int isIn(const Vector& vv, const Matrix& bck)
+ {return isIn(vv,bck,numAnnuli_-1);}
+ int isIn(const Vector& vv, const Matrix& bck, int nn)
+ {return isInRef(vv*bck,nn);}
};
#endif
diff --git a/saotk/frame/basecommand.C b/saotk/frame/basecommand.C
index 843b908..2de5375 100644
--- a/saotk/frame/basecommand.C
+++ b/saotk/frame/basecommand.C
@@ -5,7 +5,7 @@
#include <fstream>
#include "fdstream.hpp"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
diff --git a/saotk/frame/baseellipse.C b/saotk/frame/baseellipse.C
index 092b476..122e09d 100644
--- a/saotk/frame/baseellipse.C
+++ b/saotk/frame/baseellipse.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "baseellipse.h"
#include "fitsimage.h"
@@ -640,7 +642,7 @@ void BaseEllipse::updateHandles()
handle[ii+4] = fwdMap(Vector(annuli_[ii][0],0),Coord::CANVAS);
}
-int BaseEllipse::isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
+int BaseEllipse::isInRef(const Vector& vv, int nn)
{
Vector rr = annuli_[nn];
@@ -648,7 +650,7 @@ int BaseEllipse::isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
if (!rr[0] || !rr[1])
return 0;
- Vector pp = bckMap(vv,sys);
+ Vector& pp = (Vector&)vv;
if ((pp[0]*pp[0])/(rr[0]*rr[0]) + (pp[1]*pp[1])/(rr[1]*rr[1]) <= 1)
return 1;
else
diff --git a/saotk/frame/baseellipse.h b/saotk/frame/baseellipse.h
index 49a973c..6e053cd 100644
--- a/saotk/frame/baseellipse.h
+++ b/saotk/frame/baseellipse.h
@@ -55,6 +55,8 @@ class BaseEllipse : public BaseMarker {
virtual void updateHandles();
Vector intersect(Vector, double);
+ int isInRef(const Vector& vv, int);
+
public:
BaseEllipse(const BaseEllipse&);
BaseEllipse(Base* p, const Vector& ctr,
@@ -71,7 +73,14 @@ class BaseEllipse : public BaseMarker {
{return isIn(vv, Coord::CANVAS);}
int isIn(const Vector& vv, Coord::InternalSystem sys)
{return isIn(vv,sys,numAnnuli_-1);}
- int isIn(const Vector&, Coord::InternalSystem, int);
+ int isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
+ {return isInRef(bckMap(vv,sys),nn);}
+
+ // valid for non-fixed only
+ int isIn(const Vector& vv, const Matrix& bck)
+ {return isIn(vv,bck,numAnnuli_-1);}
+ int isIn(const Vector& vv, const Matrix& bck, int nn)
+ {return isInRef(vv*bck,nn);}
};
#endif
diff --git a/saotk/frame/baseline.C b/saotk/frame/baseline.C
index e2a121b..bac82fa 100644
--- a/saotk/frame/baseline.C
+++ b/saotk/frame/baseline.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "baseline.h"
#include "fitsimage.h"
diff --git a/saotk/frame/basemarker.C b/saotk/frame/basemarker.C
index 191915d..7a70a00 100644
--- a/saotk/frame/basemarker.C
+++ b/saotk/frame/basemarker.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "basemarker.h"
#include "base.h"
diff --git a/saotk/frame/box.C b/saotk/frame/box.C
index d32a815..e211bf8 100644
--- a/saotk/frame/box.C
+++ b/saotk/frame/box.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "box.h"
#include "fitsimage.h"
diff --git a/saotk/frame/boxannulus.C b/saotk/frame/boxannulus.C
index 0f18adf..817217e 100644
--- a/saotk/frame/boxannulus.C
+++ b/saotk/frame/boxannulus.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "boxannulus.h"
#include "fitsimage.h"
diff --git a/saotk/frame/bpanda.C b/saotk/frame/bpanda.C
index cb860bf..dd8310d 100644
--- a/saotk/frame/bpanda.C
+++ b/saotk/frame/bpanda.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "bpanda.h"
#include "fitsimage.h"
@@ -123,8 +125,8 @@ void Bpanda::renderMACOSX()
Vector r1 = annuli_[numAnnuli_-1]/2;
for (int ii=0; ii<numAngles_; ii++) {
- Vector rr0 = fwdMap(intersect(r0,angles_[ii]),CANVAS);
- Vector rr1 = fwdMap(intersect(r1,angles_[ii]),CANVAS);
+ Vector rr0 = fwdMap(intersect(r0,angles_[ii]),Coord::CANVAS);
+ Vector rr1 = fwdMap(intersect(r1,angles_[ii]),Coord::CANVAS);
macosxDrawLine(rr0,rr1);
}
diff --git a/saotk/frame/circle.C b/saotk/frame/circle.C
index 02c7b53..f6d1c9a 100644
--- a/saotk/frame/circle.C
+++ b/saotk/frame/circle.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "circle.h"
#include "fitsimage.h"
diff --git a/saotk/frame/colorscale.h b/saotk/frame/colorscale.h
index 3d87066..f95edfa 100644
--- a/saotk/frame/colorscale.h
+++ b/saotk/frame/colorscale.h
@@ -5,9 +5,6 @@
#ifndef __colorscale_h__
#define __colorscale_h__
-#include <tcl.h>
-#include <X11/Xlib.h>
-
#include "util.h"
// 0 background (white)
diff --git a/saotk/frame/colorscalepseudo8.C b/saotk/frame/colorscalepseudo8.C
deleted file mode 100644
index 1c317bf..0000000
--- a/saotk/frame/colorscalepseudo8.C
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "colorscalepseudo8.h"
-#include "base.h"
-
-ColorScalePseudoColor8::ColorScalePseudoColor8(int s) : ColorScale(s)
-{
- colors_ = new unsigned char[s];
-
- for (int i=0; i<s; i++)
- colors_[i] = psIndex_[i];
-}
-
-ColorScalePseudoColor8::~ColorScalePseudoColor8()
-{
- if (colors_)
- delete [] colors_;
-}
-
-LinearScalePseudoColor8::LinearScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : LinearScale(s, indexCells, colorCells, count),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-LogScalePseudoColor8::LogScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count, double exp)
- : LogScale(s, indexCells, colorCells, count, exp),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-PowScalePseudoColor8::PowScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count, double exp)
- : PowScale(s, indexCells, colorCells, count, exp),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-SqrtScalePseudoColor8::SqrtScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : SqrtScale(s, indexCells, colorCells, count),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-SquaredScalePseudoColor8::SquaredScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : SquaredScale(s, indexCells, colorCells, count),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-AsinhScalePseudoColor8::AsinhScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : AsinhScale(s, indexCells, colorCells, count),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-SinhScalePseudoColor8::SinhScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : SinhScale(s, indexCells, colorCells, count),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
-
-IISScalePseudoColor8::IISScalePseudoColor8(Base* parent,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count)
- : IISScale(indexCells, colorCells, count),
- ColorScalePseudoColor8(IISSIZE),
- ColorScale(IISSIZE)
-{
- colors_[200] = psIndex_[200] = parent->getColor("black");
- colors_[201] = psIndex_[201] = parent->getColor("black");
- colors_[202] = psIndex_[202] = parent->getColor("white");
- colors_[203] = psIndex_[203] = parent->getColor("red");
- colors_[204] = psIndex_[204] = parent->getColor("green");
- colors_[205] = psIndex_[205] = parent->getColor("blue");
- colors_[206] = psIndex_[206] = parent->getColor("yellow");
- colors_[207] = psIndex_[207] = parent->getColor("cyan");
- colors_[208] = psIndex_[208] = parent->getColor("magenta");
- colors_[209] = psIndex_[209] = parent->getColor("coral");
- colors_[210] = psIndex_[210] = parent->getColor("maroon");
- colors_[211] = psIndex_[211] = parent->getColor("orange");
- colors_[212] = psIndex_[212] = parent->getColor("khaki");
- colors_[213] = psIndex_[213] = parent->getColor("orchid");
- colors_[214] = psIndex_[214] = parent->getColor("turquoise");
- colors_[215] = psIndex_[215] = parent->getColor("violet");
- colors_[216] = psIndex_[216] = parent->getColor("wheat");
-}
-
-HistEquScalePseudoColor8::HistEquScalePseudoColor8(int s,
- unsigned short* indexCells,
- unsigned char* colorCells,
- int count,
- double* hist, int histsize)
- : HistEquScale(s, indexCells, colorCells, count, hist, histsize),
- ColorScalePseudoColor8(s),
- ColorScale(s) {}
diff --git a/saotk/frame/colorscalepseudo8.h b/saotk/frame/colorscalepseudo8.h
deleted file mode 100644
index dc16f38..0000000
--- a/saotk/frame/colorscalepseudo8.h
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __colorscalepseudo8_h__
-#define __colorscalepseudo8_h__
-
-#include "colorscale.h"
-
-class Base;
-
-class ColorScalePseudoColor8 : public virtual ColorScale {
-public:
- ColorScalePseudoColor8(int);
- virtual ~ColorScalePseudoColor8();
-};
-
-class LinearScalePseudoColor8 :
-public virtual ColorScale,
-public LinearScale,
-public ColorScalePseudoColor8 {
-public:
- LinearScalePseudoColor8(int, unsigned short*, unsigned char*, int);
-};
-
-class LogScalePseudoColor8 :
-public virtual ColorScale,
-public LogScale,
-public ColorScalePseudoColor8 {
-public:
- LogScalePseudoColor8(int, unsigned short*, unsigned char*, int, double);
-};
-
-class PowScalePseudoColor8 :
-public virtual ColorScale,
-public PowScale,
-public ColorScalePseudoColor8 {
-public:
- PowScalePseudoColor8(int, unsigned short*, unsigned char*, int, double);
-};
-
-class SqrtScalePseudoColor8 :
-public virtual ColorScale,
-public SqrtScale,
-public ColorScalePseudoColor8 {
-public:
- SqrtScalePseudoColor8(int, unsigned short*, unsigned char*, int);
-};
-
-class SquaredScalePseudoColor8 :
-public virtual ColorScale,
-public SquaredScale,
-public ColorScalePseudoColor8 {
-public:
- SquaredScalePseudoColor8(int, unsigned short*, unsigned char*, int);
-};
-
-class AsinhScalePseudoColor8 :
-public virtual ColorScale,
-public AsinhScale,
-public ColorScalePseudoColor8 {
-public:
- AsinhScalePseudoColor8(int, unsigned short*, unsigned char*, int);
-};
-
-class SinhScalePseudoColor8 :
-public virtual ColorScale,
-public SinhScale,
-public ColorScalePseudoColor8 {
-public:
- SinhScalePseudoColor8(int, unsigned short*, unsigned char*, int);
-};
-
-class IISScalePseudoColor8 :
-public virtual ColorScale,
-public IISScale,
-public ColorScalePseudoColor8 {
-public:
- IISScalePseudoColor8(Base*,unsigned short*, unsigned char*, int);
-};
-
-class HistEquScalePseudoColor8 :
-public virtual ColorScale,
-public HistEquScale,
-public ColorScalePseudoColor8 {
-public:
- HistEquScalePseudoColor8(int, unsigned short*, unsigned char*, int,
- double*, int);
-};
-
-#endif
diff --git a/saotk/frame/colorscalergb.h b/saotk/frame/colorscalergb.h
index 1db0e63..a69b61d 100644
--- a/saotk/frame/colorscalergb.h
+++ b/saotk/frame/colorscalergb.h
@@ -5,9 +5,6 @@
#ifndef __colorscalergb_h__
#define __colorscalergb_h__
-#include <tcl.h>
-#include <X11/Xlib.h>
-
#include "util.h"
class ColorScaleRGB {
diff --git a/saotk/frame/colorscaletrue32.C b/saotk/frame/colorscaletrue32.C
index 189e096..4604ea3 100644
--- a/saotk/frame/colorscaletrue32.C
+++ b/saotk/frame/colorscaletrue32.C
@@ -16,6 +16,9 @@ ColorScaleTrueColor32::ColorScaleTrueColor32(int s, Visual* visual, int msb)
unsigned int g = psColors_[i*3+1];
unsigned int b = psColors_[i*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
@@ -28,6 +31,9 @@ ColorScaleTrueColor32::ColorScaleTrueColor32(int s, Visual* visual, int msb)
unsigned int g = psColors_[i*3+1];
unsigned int b = psColors_[i*3];
unsigned int a = 0;
+#ifdef _MACOSX
+ a |= 0xff << 24;
+#endif
a |= r << rs_;
a |= g << gs_;
a |= b << bs_;
diff --git a/saotk/frame/compass.C b/saotk/frame/compass.C
index 39d714f..3a41c59 100644
--- a/saotk/frame/compass.C
+++ b/saotk/frame/compass.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "compass.h"
#include "fitsimage.h"
@@ -298,7 +300,7 @@ void Compass::renderMACOSX()
if (eastText) {
float r1 = Tk_TextWidth(psfont_, eastText, strlen(eastText))/2.;
float r2 = metrics.linespace/2.;
- double angle = (c-a).angle();
+ double angle = (cc-aa).angle();
Vector eee = ee *
Translate(r1*cos(angle),r2*sin(angle)) *
Translate(-r1,(metrics.ascent-metrics.descent)/2.);
diff --git a/saotk/frame/composite.C b/saotk/frame/composite.C
index 9c672b6..de7952c 100644
--- a/saotk/frame/composite.C
+++ b/saotk/frame/composite.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "composite.h"
#include "fitsimage.h"
diff --git a/saotk/frame/context.C b/saotk/frame/context.C
index 476accd..7500777 100644
--- a/saotk/frame/context.C
+++ b/saotk/frame/context.C
@@ -3,8 +3,6 @@
// For conditions of distribution and use, see copyright notice in "copyright"
#include "context.h"
-#include "blt.h"
-#include "bltVector.h"
#include "fitsimage.h"
#include "fvcontour.h"
@@ -19,6 +17,10 @@
#include "socketgz.h"
#include "var.h"
+extern "C" {
+#include "bltVector.h"
+}
+
Context::Context()
{
parent_ = NULL;
@@ -483,8 +485,8 @@ int Context::load(Base* parent, Base::MemType which,
if (img->isHist())
which = Base::HIST;
- else if (img->isCompress())
- which = Base::COMPRESS;
+ else if (img->isPost())
+ which = Base::POST;
FitsImage* ptr = img;
for (int ii=1; ii<img->nhdu(); ii++) {
@@ -526,8 +528,8 @@ int Context::load(Base* parent, Base::MemType which,
case Base::HIST:
next = new FitsImageFitsNextHist(parent, img, ptr->baseFile(), ii+1);
break;
- case Base::COMPRESS:
- next = new FitsImageFitsNextCompress(parent, img, ptr->baseFile(), ii+1);
+ case Base::POST:
+ next = new FitsImageFitsNextPost(parent, img, ptr->baseFile(), ii+1);
break;
case Base::PHOTO:
next = new FitsImagePhotoCubeNext(parent, fn, ptr->baseFile(), ii+1);
@@ -620,7 +622,7 @@ int Context::loadExtCube(Base* parent, Base::MemType which,
break;
}
- if (next && next->isValid() && (next->isImage() || next->isCompress())) {
+ if (next && next->isValid() && (next->isImage() || next->isPost())) {
ptr->setNextSlice(next);
ptr = next;
naxis_[2]++;
@@ -749,8 +751,8 @@ int Context::loadMosaic(Base* parent, Base::MemType which,
break;
}
- if (img->isCompress())
- which = Base::COMPRESS;
+ if (img->isPost())
+ which = Base::POST;
// get the rest of slices
FitsImage* sptr = img;
@@ -790,8 +792,8 @@ int Context::loadMosaic(Base* parent, Base::MemType which,
case Base::VAR:
next = new FitsImageFitsNextVar(parent, fn, sptr->fitsFile(), ii+1);
break;
- case Base::COMPRESS:
- next = new FitsImageFitsNextCompress(parent, img, sptr->baseFile(), ii+1);
+ case Base::POST:
+ next = new FitsImageFitsNextPost(parent, img, sptr->baseFile(), ii+1);
break;
case Base::PHOTO:
next = new FitsImagePhotoCubeNext(parent, fn, sptr->baseFile(), ii+1);
@@ -886,8 +888,8 @@ int Context::loadMosaicImage(Base* parent, Base::MemType which,
// get the rest of slices
FitsImage* sptr = img;
- if (img->isCompress())
- which = Base::COMPRESS;
+ if (img->isPost())
+ which = Base::POST;
for (int ii=1; ii<img->nhdu(); ii++) {
FitsImage* next = NULL;
@@ -925,8 +927,8 @@ int Context::loadMosaicImage(Base* parent, Base::MemType which,
case Base::VAR:
next = new FitsImageFitsNextVar(parent, fn, sptr->fitsFile(), ii+1);
break;
- case Base::COMPRESS:
- next = new FitsImageFitsNextCompress(parent, img, sptr->baseFile(), ii+1);
+ case Base::POST:
+ next = new FitsImageFitsNextPost(parent, img, sptr->baseFile(), ii+1);
break;
}
@@ -998,7 +1000,7 @@ int Context::loadMosaicImage(Base* parent, Base::MemType which,
break;
}
- if (next && next->isValid() && (next->isImage() || next->isCompress())) {
+ if (next && next->isValid() && (next->isImage() || next->isPost())) {
ptr->setNextMosaic(next);
ptr = next;
@@ -1020,8 +1022,8 @@ int Context::loadMosaicImage(Base* parent, Base::MemType which,
if (ll == Base::IMG)
mosaicCount_++;
- if (img->isCompress())
- which = Base::COMPRESS;
+ if (img->isPost())
+ which = Base::POST;
// get rest of slices
for (int ii=1; ii<img->nhdu(); ii++) {
@@ -1060,8 +1062,8 @@ int Context::loadMosaicImage(Base* parent, Base::MemType which,
case Base::VAR:
snext = new FitsImageFitsNextVar(parent, fn, next->fitsFile(), ii+1);
break;
- case Base::COMPRESS:
- snext = new FitsImageFitsNextCompress(parent, ptr, next->baseFile(), ii+1);
+ case Base::POST:
+ snext = new FitsImageFitsNextPost(parent, ptr, next->baseFile(), ii+1);
break;
}
@@ -1131,8 +1133,8 @@ int Context::loadMosaicWFPC2(Base* parent, Base::MemType which,
// remember in case of compress
Base::MemType sav = which;
- if (img->isCompress())
- which = Base::COMPRESS;
+ if (img->isPost())
+ which = Base::POST;
// get the rest
{
@@ -1167,8 +1169,8 @@ int Context::loadMosaicWFPC2(Base* parent, Base::MemType which,
case Base::VAR:
next = new FitsImageFitsNextVar(parent, fn, ptr->fitsFile(), 1);
break;
- case Base::COMPRESS:
- next = new FitsImageFitsNextCompress(parent, img, ptr->baseFile(), 1);
+ case Base::POST:
+ next = new FitsImageFitsNextPost(parent, img, ptr->baseFile(), 1);
break;
}
diff --git a/saotk/frame/context.h b/saotk/frame/context.h
index 8f6004d..f1fd192 100644
--- a/saotk/frame/context.h
+++ b/saotk/frame/context.h
@@ -5,7 +5,6 @@
#ifndef __context_h__
#define __context_h__
-#include "tcl.h"
#include "base.h"
#include "coord.h"
#include "frscale.h"
diff --git a/saotk/frame/contour.h b/saotk/frame/contour.h
index 1301b51..70a968d 100644
--- a/saotk/frame/contour.h
+++ b/saotk/frame/contour.h
@@ -5,6 +5,9 @@
#ifndef __contour_h__
#define __contour_h__
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
#include "vector.h"
#include "vector3d.h"
#include "list.h"
diff --git a/saotk/frame/cpanda.C b/saotk/frame/cpanda.C
index c43fd0e..d62ad68 100644
--- a/saotk/frame/cpanda.C
+++ b/saotk/frame/cpanda.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "cpanda.h"
#include "fitsimage.h"
diff --git a/saotk/frame/ellipse.C b/saotk/frame/ellipse.C
index 8c40348..e329869 100644
--- a/saotk/frame/ellipse.C
+++ b/saotk/frame/ellipse.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "ellipse.h"
#include "fitsimage.h"
diff --git a/saotk/frame/ellipseannulus.C b/saotk/frame/ellipseannulus.C
index 5e5518a..421f418 100644
--- a/saotk/frame/ellipseannulus.C
+++ b/saotk/frame/ellipseannulus.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "ellipseannulus.h"
#include "fitsimage.h"
diff --git a/saotk/frame/epanda.C b/saotk/frame/epanda.C
index f9945c8..a08a675 100644
--- a/saotk/frame/epanda.C
+++ b/saotk/frame/epanda.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "epanda.h"
#include "fitsimage.h"
diff --git a/saotk/frame/fitscompress.C b/saotk/frame/fitscompress.C
index e0cd36a..35ad182 100644
--- a/saotk/frame/fitscompress.C
+++ b/saotk/frame/fitscompress.C
@@ -19,104 +19,104 @@ void FitsImage::initCompress()
return ;
}
- if (compress_)
- delete compress_;
- compress_ = NULL;
+ if (post_)
+ delete post_;
+ post_ = NULL;
if (!strncmp(type,"RICE",4))
switch (bitpix) {
case 8:
- compress_ = new FitsRicem<unsigned char>(fits_);
+ post_ = new FitsRicem<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsRicem<short>(fits_);
+ post_ = new FitsRicem<short>(fits_);
break;
case -16:
- compress_ = new FitsRicem<unsigned short>(fits_);
+ post_ = new FitsRicem<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsRicem<int>(fits_);
+ post_ = new FitsRicem<int>(fits_);
break;
case 64:
- compress_ = new FitsRicem<long long>(fits_);
+ post_ = new FitsRicem<long long>(fits_);
break;
case -32:
- compress_ = new FitsRicem<float>(fits_);
+ post_ = new FitsRicem<float>(fits_);
break;
case -64:
- compress_ = new FitsRicem<double>(fits_);
+ post_ = new FitsRicem<double>(fits_);
break;
}
else if (!strncmp(type,"GZIP",4))
switch (bitpix) {
case 8:
- compress_ = new FitsGzipm<unsigned char>(fits_);
+ post_ = new FitsGzipm<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsGzipm<short>(fits_);
+ post_ = new FitsGzipm<short>(fits_);
break;
case -16:
- compress_ = new FitsGzipm<unsigned short>(fits_);
+ post_ = new FitsGzipm<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsGzipm<int>(fits_);
+ post_ = new FitsGzipm<int>(fits_);
break;
case 64:
- compress_ = new FitsGzipm<long long>(fits_);
+ post_ = new FitsGzipm<long long>(fits_);
break;
case -32:
- compress_ = new FitsGzipm<float>(fits_);
+ post_ = new FitsGzipm<float>(fits_);
break;
case -64:
- compress_ = new FitsGzipm<double>(fits_);
+ post_ = new FitsGzipm<double>(fits_);
break;
}
else if (!strncmp(type,"PLIO",4))
switch (bitpix) {
case 8:
- compress_ = new FitsPliom<unsigned char>(fits_);
+ post_ = new FitsPliom<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsPliom<short>(fits_);
+ post_ = new FitsPliom<short>(fits_);
break;
case -16:
- compress_ = new FitsPliom<unsigned short>(fits_);
+ post_ = new FitsPliom<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsPliom<int>(fits_);
+ post_ = new FitsPliom<int>(fits_);
break;
case 64:
- compress_ = new FitsPliom<long long>(fits_);
+ post_ = new FitsPliom<long long>(fits_);
break;
case -32:
- compress_ = new FitsPliom<float>(fits_);
+ post_ = new FitsPliom<float>(fits_);
break;
case -64:
- compress_ = new FitsPliom<double>(fits_);
+ post_ = new FitsPliom<double>(fits_);
break;
}
else if (!strncmp(type,"HCOMPRESS",4))
switch (bitpix) {
case 8:
- compress_ = new FitsHcompressm<unsigned char>(fits_);
+ post_ = new FitsHcompressm<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsHcompressm<short>(fits_);
+ post_ = new FitsHcompressm<short>(fits_);
break;
case -16:
- compress_ = new FitsHcompressm<unsigned short>(fits_);
+ post_ = new FitsHcompressm<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsHcompressm<int>(fits_);
+ post_ = new FitsHcompressm<int>(fits_);
break;
case 64:
- compress_ = new FitsHcompressm<long long>(fits_);
+ post_ = new FitsHcompressm<long long>(fits_);
break;
case -32:
- compress_ = new FitsHcompressm<float>(fits_);
+ post_ = new FitsHcompressm<float>(fits_);
break;
case -64:
- compress_ = new FitsHcompressm<double>(fits_);
+ post_ = new FitsHcompressm<double>(fits_);
break;
}
diff --git a/saotk/frame/fitsenvi.C b/saotk/frame/fitsenvi.C
index 4f76908..fd7113c 100644
--- a/saotk/frame/fitsenvi.C
+++ b/saotk/frame/fitsenvi.C
@@ -7,9 +7,9 @@
void FitsImage::initENVI()
{
- if (compress_)
- delete compress_;
- compress_ = NULL;
+ if (post_)
+ delete post_;
+ post_ = NULL;
switch (fits_->pEncoding()) {
case FitsFile::BSQ:
@@ -18,50 +18,50 @@ void FitsImage::initENVI()
case FitsFile::BIL:
switch (fits_->pBitpix()) {
case 8:
- compress_ = new FitsENVIBILm<unsigned char>(fits_);
+ post_ = new FitsENVIBILm<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsENVIBILm<short>(fits_);
+ post_ = new FitsENVIBILm<short>(fits_);
break;
case -16:
- compress_ = new FitsENVIBILm<unsigned short>(fits_);
+ post_ = new FitsENVIBILm<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsENVIBILm<int>(fits_);
+ post_ = new FitsENVIBILm<int>(fits_);
break;
case 64:
- compress_ = new FitsENVIBILm<long long>(fits_);
+ post_ = new FitsENVIBILm<long long>(fits_);
break;
case -32:
- compress_ = new FitsENVIBILm<float>(fits_);
+ post_ = new FitsENVIBILm<float>(fits_);
break;
case -64:
- compress_ = new FitsENVIBILm<double>(fits_);
+ post_ = new FitsENVIBILm<double>(fits_);
break;
}
break;
case FitsFile::BIP:
switch (fits_->pBitpix()) {
case 8:
- compress_ = new FitsENVIBIPm<unsigned char>(fits_);
+ post_ = new FitsENVIBIPm<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsENVIBIPm<short>(fits_);
+ post_ = new FitsENVIBIPm<short>(fits_);
break;
case -16:
- compress_ = new FitsENVIBIPm<unsigned short>(fits_);
+ post_ = new FitsENVIBIPm<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsENVIBIPm<int>(fits_);
+ post_ = new FitsENVIBIPm<int>(fits_);
break;
case 64:
- compress_ = new FitsENVIBIPm<long long>(fits_);
+ post_ = new FitsENVIBIPm<long long>(fits_);
break;
case -32:
- compress_ = new FitsENVIBIPm<float>(fits_);
+ post_ = new FitsENVIBIPm<float>(fits_);
break;
case -64:
- compress_ = new FitsENVIBIPm<double>(fits_);
+ post_ = new FitsENVIBIPm<double>(fits_);
break;
}
break;
diff --git a/saotk/frame/fitsimage.C b/saotk/frame/fitsimage.C
index f0de139..67b0528 100644
--- a/saotk/frame/fitsimage.C
+++ b/saotk/frame/fitsimage.C
@@ -63,7 +63,7 @@ FitsImage::FitsImage(Base* p)
iisFileName = NULL;
fits_ = NULL;
- compress_ = NULL;
+ post_ = NULL;
hist_ = NULL;
hpx_ = NULL;
@@ -147,8 +147,8 @@ FitsImage::~FitsImage()
if (fits_)
delete fits_;
- if (compress_)
- delete compress_;
+ if (post_)
+ delete post_;
if (hist_)
delete hist_;
@@ -409,12 +409,12 @@ FitsImageFitsNextHist::FitsImageFitsNextHist(Base* p,
iisFileName = dupstr(fi->getFullBaseFileName());
}
-FitsImageFitsNextCompress::FitsImageFitsNextCompress(Base* p,
- FitsImage* fi,
- FitsFile* prev, int id)
+FitsImageFitsNextPost::FitsImageFitsNextPost(Base* p,
+ FitsImage* fi,
+ FitsFile* prev, int id)
: FitsImage(p)
{
- fits_ = new FitsCompressNext(prev);
+ fits_ = new FitsPostNext(prev);
process(NULL,id);
rootBaseFileName = dupstr(fi->getRootBaseFileName());
@@ -1195,8 +1195,8 @@ void FitsImage::initWCS0(const Vector& pix)
void FitsImage::load()
{
- if (compress_)
- base_ = compress_;
+ if (post_)
+ base_ = post_;
else if (hpx_)
base_ = hpx_;
else if (hist_)
@@ -1478,7 +1478,7 @@ void FitsImage::process(const char* fn, int id)
break;
case FitsFile::GZIP:
initNRRD();
- if (!compress_->isValid()) {
+ if (!post_->isValid()) {
reset();
return;
}
@@ -1486,7 +1486,7 @@ void FitsImage::process(const char* fn, int id)
case FitsFile::BIL:
case FitsFile::BIP:
initENVI();
- if (!compress_->isValid()) {
+ if (!post_->isValid()) {
reset();
return;
}
@@ -1502,7 +1502,7 @@ void FitsImage::process(const char* fn, int id)
// Compress
if (fits_->find("ZIMAGE")) {
initCompress();
- if (!compress_->isValid()) {
+ if (!post_->isValid()) {
reset();
return;
}
@@ -1883,9 +1883,9 @@ void FitsImage::reset()
delete fits_;
fits_ = NULL;
- if (compress_)
- delete compress_;
- compress_ = NULL;
+ if (post_)
+ delete post_;
+ post_ = NULL;
if (hpx_)
delete hpx_;
hpx_ = NULL;
@@ -2101,7 +2101,7 @@ void FitsImage::setFileName(const char* fn)
// strip any '[]'
char* ffn = strip(fn);
- FitsFile* ptr = compress_ ? compress_ : fits_;
+ FitsFile* ptr = post_ ? post_ : fits_;
if (!ptr)
return;
@@ -3050,7 +3050,8 @@ void FitsImage::astinit(int ii, FitsHead* hh)
return;
}
- // DSS,PLT,HPX,TAB goes straight to AST
+ // DSS,PLT,LIN goes straight to AST
+ // we can't send 3D directly to AST
if (wcs[ii]->prjcode==WCS_DSS ||
wcs[ii]->prjcode==WCS_PLT ||
(wcs[ii]->prjcode==WCS_LIN && !strncmp(wcs[ii]->ptype,"HPX",3)) ||
@@ -3279,9 +3280,14 @@ AstFrameSet* FitsImage::wcs2ast(int ww)
pc << "PC1_1" << alt << ends;
if (fits->find(cd.str().c_str(), wcsHeader)) {
- if (!wcs[ww]->cd[1] && !wcs[ww]->cd[2] && !wcs[ww]->rot &&
- wcs[ww]->latpole == 999 && wcs[ww]->longpole == 999) {
- // simple case
+ // simple case CD
+ // no rotation, no poles, no LIN, no inner cd values
+ if (!wcs[ww]->cd[1] && !wcs[ww]->cd[2] &&
+ !wcs[ww]->rot &&
+ wcs[ww]->latpole == 999 &&
+ wcs[ww]->longpole == 999 &&
+ wcs[ww]->prjcode != WCS_PIX &&
+ wcs[ww]->prjcode != WCS_LIN) {
putFitsCard(chan, "CDELT1", wcs[ww]->cdelt[0]);
putFitsCard(chan, "CDELT2", wcs[ww]->cdelt[1]);
}
@@ -3292,6 +3298,7 @@ AstFrameSet* FitsImage::wcs2ast(int ww)
putFitsCard(chan, "CD2_2", wcs[ww]->cd[3]);
}
}
+ // CDELT
else if (fits->find(cdelt.str().c_str(), wcsHeader)) {
putFitsCard(chan, "CDELT1", wcs[ww]->cdelt[0]);
putFitsCard(chan, "CDELT2", wcs[ww]->cdelt[1]);
@@ -3315,11 +3322,11 @@ AstFrameSet* FitsImage::wcs2ast(int ww)
putFitsCard(chan, "CROTA2", wcs[ww]->rot);
}
}
+ // sanity check
else if (!wcs[ww]->cd[0] &&
!wcs[ww]->cd[1] &&
!wcs[ww]->cd[2] &&
!wcs[ww]->cd[3]) {
- // sanity check
putFitsCard(chan, "CDELT1", wcs[ww]->cdelt[0]);
putFitsCard(chan, "CDELT2", wcs[ww]->cdelt[1]);
putFitsCard(chan, "PC1_1", wcs[ww]->pc[0]);
@@ -3327,6 +3334,7 @@ AstFrameSet* FitsImage::wcs2ast(int ww)
putFitsCard(chan, "PC2_1", wcs[ww]->pc[2]);
putFitsCard(chan, "PC2_2", wcs[ww]->pc[3]);
}
+ // fall back
else {
putFitsCard(chan, "CD1_1", wcs[ww]->cd[0]);
putFitsCard(chan, "CD1_2", wcs[ww]->cd[1]);
diff --git a/saotk/frame/fitsimage.h b/saotk/frame/fitsimage.h
index 17949d0..ff0e38e 100644
--- a/saotk/frame/fitsimage.h
+++ b/saotk/frame/fitsimage.h
@@ -39,7 +39,7 @@ class FitsImage {
FitsFile* fits_;
// base
- FitsFile* compress_; // fits compressed
+ FitsFile* post_; // fits post processing
FitsFile* hist_; // fits bin
FitsFile* hpx_; // healpix
@@ -218,7 +218,7 @@ class FitsImage {
FitsFile* imageFile() {return image_;}
int isValid() {return image_ ? 1 : 0;}
- int isCompress() {return compress_ ? 1 : 0;}
+ int isPost() {return post_ ? 1 : 0;}
int isHist() {return hist_ ? 1 : 0;}
int isHPX() {return hpx_ ? 1 : 0;}
@@ -585,9 +585,9 @@ public:
FitsImageFitsNextHist(Base*, FitsImage*, FitsFile*, int);
};
-class FitsImageFitsNextCompress : public FitsImage {
+class FitsImageFitsNextPost : public FitsImage {
public:
- FitsImageFitsNextCompress(Base*, FitsImage*, FitsFile*, int);
+ FitsImageFitsNextPost(Base*, FitsImage*, FitsFile*, int);
};
// Array
diff --git a/saotk/frame/fitsmask.C b/saotk/frame/fitsmask.C
index e025e07..feced2b 100644
--- a/saotk/frame/fitsmask.C
+++ b/saotk/frame/fitsmask.C
@@ -2,6 +2,10 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
#include "fitsmask.h"
#include "base.h"
#include "fitsimage.h"
diff --git a/saotk/frame/fitsmask.h b/saotk/frame/fitsmask.h
index 5eb2e5f..b56e8fe 100644
--- a/saotk/frame/fitsmask.h
+++ b/saotk/frame/fitsmask.h
@@ -5,7 +5,6 @@
#ifndef __fitsmask_h__
#define __fitsmask_h__
-#include "tcl.h"
#include <X11/Xlib.h>
class Base;
diff --git a/saotk/frame/fitsnrrd.C b/saotk/frame/fitsnrrd.C
index 613d7fd..bd1607c 100644
--- a/saotk/frame/fitsnrrd.C
+++ b/saotk/frame/fitsnrrd.C
@@ -7,9 +7,9 @@
void FitsImage::initNRRD()
{
- if (compress_)
- delete compress_;
- compress_ = NULL;
+ if (post_)
+ delete post_;
+ post_ = NULL;
switch (fits_->pEncoding()) {
case FitsFile::RAW:
@@ -17,25 +17,25 @@ void FitsImage::initNRRD()
case FitsFile::GZIP:
switch (fits_->pBitpix()) {
case 8:
- compress_ = new FitsNRRDGzipm<unsigned char>(fits_);
+ post_ = new FitsNRRDGzipm<unsigned char>(fits_);
break;
case 16:
- compress_ = new FitsNRRDGzipm<short>(fits_);
+ post_ = new FitsNRRDGzipm<short>(fits_);
break;
case -16:
- compress_ = new FitsNRRDGzipm<unsigned short>(fits_);
+ post_ = new FitsNRRDGzipm<unsigned short>(fits_);
break;
case 32:
- compress_ = new FitsNRRDGzipm<int>(fits_);
+ post_ = new FitsNRRDGzipm<int>(fits_);
break;
case 64:
- compress_ = new FitsNRRDGzipm<long long>(fits_);
+ post_ = new FitsNRRDGzipm<long long>(fits_);
break;
case -32:
- compress_ = new FitsNRRDGzipm<float>(fits_);
+ post_ = new FitsNRRDGzipm<float>(fits_);
break;
case -64:
- compress_ = new FitsNRRDGzipm<double>(fits_);
+ post_ = new FitsNRRDGzipm<double>(fits_);
break;
}
break;
diff --git a/saotk/frame/fr3dcommand.C b/saotk/frame/fr3dcommand.C
index 1acf396..da98df5 100644
--- a/saotk/frame/fr3dcommand.C
+++ b/saotk/frame/fr3dcommand.C
@@ -2,8 +2,6 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
-
#include "frame3dbase.h"
#include "fitsimage.h"
#include "context.h"
diff --git a/saotk/frame/frame3dbase.C b/saotk/frame/frame3dbase.C
index 9764fdd..1d2da29 100644
--- a/saotk/frame/frame3dbase.C
+++ b/saotk/frame/frame3dbase.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -1023,10 +1023,10 @@ void Frame3dBase::ximageToPixmapMagnifier()
XImage* srcXImage = XGetImage(display, basePixmap, uu[0], uu[1],
zz[0], zz[1], AllPlanes, ZPixmap);
- char* src = XImageData(srcXImage);
+ char* src = srcXImage->data;
int srcBytesPerLine = srcXImage->bytes_per_line;
- char* dst = XImageData(magnifierXImage);
+ char* dst = magnifierXImage->data;
int dstBytesPerLine = magnifierXImage->bytes_per_line;
int bytesPerPixel = magnifierXImage->bits_per_pixel/8;
@@ -1140,7 +1140,7 @@ void Frame3dBase::macosxHighlite()
{
Vector vv[4];
int rr[4];
- calcHighlite(CANVAS,vv,rr);
+ calcHighlite(Coord::CANVAS,vv,rr);
macosxColor(getXColor(highliteColorName_));
macosxWidth(1);
diff --git a/saotk/frame/frame3dtrue.C b/saotk/frame/frame3dtrue.C
index 2a70f33..071b77c 100644
--- a/saotk/frame/frame3dtrue.C
+++ b/saotk/frame/frame3dtrue.C
@@ -2,10 +2,6 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
#include "frame3dtrue.h"
Frame3dTrue::Frame3dTrue(Tcl_Interp* i, Tk_Canvas c, Tk_Item* item)
diff --git a/saotk/frame/frame3dtruecolor.C b/saotk/frame/frame3dtruecolor.C
index 07e1c58..e9a6c3c 100644
--- a/saotk/frame/frame3dtruecolor.C
+++ b/saotk/frame/frame3dtruecolor.C
@@ -2,10 +2,6 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
#include "frame3dtruecolor.h"
#include "fitsimage.h"
#include "ps.h"
diff --git a/saotk/frame/framebase.C b/saotk/frame/framebase.C
index 9171c93..b899314 100644
--- a/saotk/frame/framebase.C
+++ b/saotk/frame/framebase.C
@@ -2,10 +2,6 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
#include "framebase.h"
#include "fitsimage.h"
#include "marker.h"
diff --git a/saotk/frame/framepseudo.C b/saotk/frame/framepseudo.C
deleted file mode 100644
index b1ef1de..0000000
--- a/saotk/frame/framepseudo.C
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "framepseudo.h"
-
-FramePseudo::FramePseudo(Tcl_Interp* i, Tk_Canvas c, Tk_Item* item)
- : FrameBase(i, c, item)
-{
-}
-
-FramePseudo::~FramePseudo()
-{
-}
-
-void FramePseudo::rotateMotion()
-{
- // Rotate from src to dest
- Vector c = Vector(options->width,options->height)/2;
- Matrix m = (Translate(-c) *
- Rotate(rotation-rotateRotation) * Translate(c)).invert();
- double* mm = m.mm();
- unsigned long bgc = getColor(bgColorName);
-
- int& width = options->width;
- int& height = options->height;
- char* src = XImageData(rotateSrcXM);
-
- for (int j=0; j<height; j++) {
- // the line may be padded at the end
- char* dest = XImageData(rotateDestXM) + j*rotateDestXM->bytes_per_line;
-
- for (int i=0; i<width; i++, dest++) {
- double x = i*mm[0] + j*mm[3] + mm[6];
- double y = i*mm[1] + j*mm[4] + mm[7];
-
- if (x >= 0 && x < width && y >= 0 && y < height)
- *dest = src[((int)y)*rotateSrcXM->bytes_per_line + (int)x];
- else
- *dest = bgc;
- }
- }
-
- // XImage to Pixmap
- XPutImage(display, rotatePM, gc, rotateDestXM,
- 0, 0, 0, 0, options->width, options->height);
-
- // Display Pixmap
- Vector dd = Vector() * widgetToWindow;
- XCopyArea(display, rotatePM, Tk_WindowId(tkwin), rotateGCXOR, 0, 0,
- options->width, options->height, dd[0], dd[1]);
-}
-
diff --git a/saotk/frame/framepseudo.h b/saotk/frame/framepseudo.h
deleted file mode 100644
index e64f0e7..0000000
--- a/saotk/frame/framepseudo.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __framepseudo_h__
-#define __framepseudo_h__
-
-#include "framebase.h"
-
-class FramePseudo : public virtual FrameBase {
- protected:
- void encodeTrueColor(int,int) {}
- void rotateMotion();
-
- public:
- FramePseudo(Tcl_Interp*, Tk_Canvas, Tk_Item*);
- virtual ~FramePseudo();
-};
-
-#endif
diff --git a/saotk/frame/framepseudocolor.C b/saotk/frame/framepseudocolor.C
deleted file mode 100644
index 9dfc751..0000000
--- a/saotk/frame/framepseudocolor.C
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "framepseudocolor.h"
-#include "fitsimage.h"
-#include "ps.h"
-
-#include "sigbus.h"
-
-FramePseudoColor::FramePseudoColor(Tcl_Interp* i, Tk_Canvas c, Tk_Item* item)
- : FrameBase(i,c,item), Frame(i,c,item), FramePseudo(i,c,item)
-{
-}
-
-void FramePseudoColor::buildXImage(XImage* xmap, Coord::InternalSystem sys)
-{
- // we need a colorScale before we can render
- if (!validColorScale())
- return;
-
- // make sure we have an image
- if (!context->cfits)
- return;
-
- int& width = xmap->width;
- int& height = xmap->height;
- int& bytesPerLine = xmap->bytes_per_line;
- char* data = XImageData(xmap);
- unsigned long bgc = getColor(bgColorName);
- unsigned long nanc = getColor(nanColorName);
-
- // set bg
- memset(data, bgc, bytesPerLine * height);
-
- // basics
- int length = colorScale->size() - 1;
- const unsigned char* table = colorScale->colors();
-
- FitsImage* sptr = context->cfits;
- int mosaic = isMosaic();
-
- // variable
- double* mm = sptr->matrixToData(sys).mm();
- FitsBound* params = sptr->getDataParams(context->frScale.scanMode());
- int srcw = sptr->width();
-
- double ll = sptr->getLowDouble();
- double hh = sptr->getHighDouble();
- double diff = hh - ll;
-
- // main loop
- SETSIGBUS
- for (long jj=0; jj<height; jj++) {
- char* dest = data + jj*bytesPerLine; // may be padded at the end
-
- for (long ii=0; ii<width; ii++,dest++) {
-
- if (mosaic) {
- sptr = context->cfits;
-
- mm = sptr->matrixToData(sys).mm();
- params = sptr->getDataParams(context->frScale.scanMode());
- srcw = sptr->width();
-
- ll = sptr->getLowDouble();
- hh = sptr->getHighDouble();
- diff = hh - ll;
- }
-
- do {
- double xx = ii*mm[0] + jj*mm[3] + mm[6];
- double yy = ii*mm[1] + jj*mm[4] + mm[7];
-
- if (xx>=params->xmin && xx<params->xmax &&
- yy>=params->ymin && yy<params->ymax) {
- double value = sptr->getValueDouble(long(yy)*srcw + long(xx));
-
- if (isfinite(value)) {
- if (value <= ll)
- *dest = table[0];
- else if (value >= hh)
- *dest = table[length];
- else
- *dest = table[(int)(((value - ll)/diff * length) + .5)];
- }
- else
- *dest = nanc;
-
- break;
- }
- else {
- if (mosaic) {
- sptr = sptr->nextMosaic();
-
- if (sptr) {
- mm = sptr->matrixToData(sys).mm();
- params = sptr->getDataParams(context->frScale.scanMode());
- srcw = sptr->width();
-
- ll = sptr->getLowDouble();
- hh = sptr->getHighDouble();
- diff = hh - ll;
- }
- }
- }
- }
- while (mosaic && sptr);
- }
- }
- CLEARSIGBUS
-}
-
-// Commands
-
-void FramePseudoColor::colormapCmd(int id, float b, float c, int i,
- unsigned short* index,
- unsigned char* cells, int cnt)
-{
- cmapID = id;
- bias = b;
- contrast = c;
- invert = i;
-
- updateColorCells(index, cells, cnt);
- updateColorScale();
-}
-
-void FramePseudoColor::colormapMotionCmd(int id, float b, float c, int i,
- unsigned short* index,
- unsigned char* cells, int cnt)
-{
- // just remember for getColorbarCmd()
- cmapID = id;
- bias = b;
- contrast = c;
- invert = i;
-}
-
-void FramePseudoColor::colormapEndCmd()
-{
- update(BASE); // always update
-}
diff --git a/saotk/frame/framepseudocolor.h b/saotk/frame/framepseudocolor.h
deleted file mode 100644
index ae6f870..0000000
--- a/saotk/frame/framepseudocolor.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __framepseudocolor_h__
-#define __framepseudocolor_h__
-
-#include "frame.h"
-#include "framepseudo.h"
-
-class FramePseudoColor : public virtual FrameBase, public Frame, public FramePseudo {
-private:
- void buildXImage(XImage* xmap, Coord::InternalSystem);
-
-public:
- FramePseudoColor(Tcl_Interp*, Tk_Canvas, Tk_Item*);
-
- void colormapCmd(int, float, float, int, unsigned short*,
- unsigned char*, int);
- void colormapMotionCmd(int id, float b, float c, int i,
- unsigned short* index,
- unsigned char* cells, int cnt);
- void colormapEndCmd();
-};
-
-#endif
diff --git a/saotk/frame/framepseudocolor8.C b/saotk/frame/framepseudocolor8.C
deleted file mode 100644
index 80d338f..0000000
--- a/saotk/frame/framepseudocolor8.C
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "framepseudocolor8.h"
-#include "colorscalepseudo8.h"
-
-// Tk Canvas Widget Function Declarations
-
-int FramePseudoColor8CreateProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int,
- Tcl_Obj *const []);
-
-// FramePseudoColor8 Specs
-
-static Tk_CustomOption tagsOption = {
- Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
-};
-
-static Tk_ConfigSpec framePseudoColor8Specs[] = {
-
- {TK_CONFIG_STRING, (char*)"-command", NULL, NULL, "frame",
- Tk_Offset(WidgetOptions, cmdName), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-x", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, x), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-y", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, y), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-width", NULL, NULL, "512",
- Tk_Offset(WidgetOptions, width), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-height", NULL, NULL, "512",
- Tk_Offset(WidgetOptions, height), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_ANCHOR, (char*)"-anchor", NULL, NULL, "nw",
- Tk_Offset(WidgetOptions, anchor), 0, NULL},
- {TK_CONFIG_CUSTOM, (char*)"-tags", NULL, NULL, NULL,
- 0, TK_CONFIG_NULL_OK, &tagsOption},
-
- {TK_CONFIG_STRING, (char*)"-helvetica", NULL, NULL, "helvetica",
- Tk_Offset(WidgetOptions, helvetica), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-courier", NULL, NULL, "courier",
- Tk_Offset(WidgetOptions, courier), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-times", NULL, NULL, "times",
- Tk_Offset(WidgetOptions, times), 0, NULL},
-
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL},
-};
-
-// Tk Static Structure
-
-static Tk_ItemType framePseudoColor8Type = {
- (char*)"framepseudocolor8", // name
- sizeof(WidgetOptions), // item size
- FramePseudoColor8CreateProc, // configProc
- framePseudoColor8Specs, // configSpecs
- WidgetConfigProc, // configProc
- WidgetCoordProc, // coordProc
- WidgetDeleteProc, // deleteProc
- WidgetDisplayProc, // displayProc
- 0, // alwaysRedraw
- WidgetPointProc, // pointProc
- WidgetAreaProc, // areaProc
- WidgetPostscriptProc, // postscriptProc
- WidgetScaleProc, // scaleProc
- WidgetTranslateProc, // translateProc
- (Tk_ItemIndexProc*)NULL, // indexProc
- WidgetICursorProc, // icursorProc
- (Tk_ItemSelectionProc*)NULL, // selectionProc
- (Tk_ItemInsertProc*)NULL, // insertProc
- (Tk_ItemDCharsProc*)NULL, // dCharsProc
- (Tk_ItemType*)NULL // nextPtr
-};
-
-// Non-Member Functions
-
-int FramePseudoColor8_Init(Tcl_Interp* interp)
-{
- Tk_CreateItemType(&framePseudoColor8Type);
- return TCL_OK;
-}
-
-int FramePseudoColor8CreateProc(Tcl_Interp* interp, Tk_Canvas canvas,
- Tk_Item* item, int argc, Tcl_Obj *const argv[])
-{
- FramePseudoColor8* frame = new FramePseudoColor8(interp, canvas, item);
-
- // and set default configuration
-
- if (frame->configure(argc, (const char**)argv, 0) != TCL_OK) {
- delete frame;
- Tcl_AppendResult(interp, " error occured while creating frame.", NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-// FramePseudoColor8 Member Functions
-
-FramePseudoColor8::FramePseudoColor8(Tcl_Interp* i, Tk_Canvas c, Tk_Item* item)
- : FrameBase(i,c,item), FramePseudoColor(i,c,item)
-{
- configSpecs = framePseudoColor8Specs; // frame configure options
-}
-
-FramePseudoColor8::~FramePseudoColor8()
-{
- // we must do this at this level, because updateColorScale is called
- unloadAllFits();
-}
-
-void FramePseudoColor8::updateColorScale()
-{
- // we need colors before we can construct a scale
-
- if (!indexCells || !colorCells)
- return;
-
- if (colorScale)
- delete colorScale;
-
- switch (context->frScale.colorScaleType()) {
- case FrScale::LINEARSCALE:
- colorScale =
- new LinearScalePseudoColor8(colorCount, indexCells, colorCells,
- colorCount);
- break;
- case FrScale::LOGSCALE:
- colorScale = new LogScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount, context->frScale.expo());
- break;
- case FrScale::POWSCALE:
- colorScale = new PowScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount, context->frScale.expo());
- break;
- case FrScale::SQRTSCALE:
- colorScale =
- new SqrtScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount);
- break;
- case FrScale::SQUAREDSCALE:
- colorScale =
- new SquaredScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount);
- break;
- case FrScale::ASINHSCALE:
- colorScale =
- new AsinhScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount);
- break;
- case FrScale::SINHSCALE:
- colorScale =
- new SinhScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount);
- break;
- case FrScale::HISTEQUSCALE:
- colorScale =
- new HistEquScalePseudoColor8(SCALESIZE, indexCells, colorCells,
- colorCount, context->histequ(),
- HISTEQUSIZE);
- break;
- case FrScale::IISSCALE:
- colorScale =
- new IISScalePseudoColor8(this,indexCells, colorCells,
- colorCount);
- break;
- }
-}
-
-
diff --git a/saotk/frame/framepseudocolor8.h b/saotk/frame/framepseudocolor8.h
deleted file mode 100644
index 33b29f8..0000000
--- a/saotk/frame/framepseudocolor8.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __framepseudocolor8_h__
-#define __framepseudocolor8_h__
-
-#include "framepseudocolor.h"
-
-class FramePseudoColor8 : public virtual FrameBase, public FramePseudoColor {
-private:
- void encodeTrueColor(XColor*, char*) {}
- void encodeTrueColor(unsigned char*, XImage*) {}
- void updateColorScale();
-
-public:
- FramePseudoColor8(Tcl_Interp*, Tk_Canvas, Tk_Item*);
- ~FramePseudoColor8();
-};
-
-#endif
diff --git a/saotk/frame/framergb.C b/saotk/frame/framergb.C
index dbebf6a..70a55f8 100644
--- a/saotk/frame/framergb.C
+++ b/saotk/frame/framergb.C
@@ -264,13 +264,13 @@ BBox FrameRGB::imageBBox(FrScale::ScanMode mode)
void FrameRGB::loadRGBCube(MemType which, const char* fn, FitsImage* img)
{
- if (!img || !img->isValid() || !(img->isImage() || img->isCompress()) || (img->depth() != 3))
+ if (!img || !img->isValid() || !(img->isImage() || img->isPost()) || (img->depth() != 3))
goto error;
context[0].fits = img;
- if (img->isCompress())
- which = COMPRESS;
+ if (img->isPost())
+ which = POST;
switch (which) {
case ALLOC:
@@ -339,11 +339,11 @@ void FrameRGB::loadRGBCube(MemType which, const char* fn, FitsImage* img)
if (context[1].fits && context[1].fits->isValid())
context[2].fits = new FitsImageFitsNextVar(this, fn, context[1].fits->fitsFile(),3);
break;
- case COMPRESS:
+ case POST:
if (context[0].fits && context[0].fits->isValid())
- context[1].fits = new FitsImageFitsNextCompress(this, img,context[0].fits->baseFile(),2);
+ context[1].fits = new FitsImageFitsNextPost(this, img,context[0].fits->baseFile(),2);
if (context[1].fits && context[1].fits->isValid())
- context[2].fits = new FitsImageFitsNextCompress(this, img,context[1].fits->baseFile(),3);
+ context[2].fits = new FitsImageFitsNextPost(this, img,context[1].fits->baseFile(),3);
break;
case PHOTO:
if (context[0].fits && context[0].fits->isValid())
@@ -355,11 +355,11 @@ void FrameRGB::loadRGBCube(MemType which, const char* fn, FitsImage* img)
// is everything ok?
if (context[0].fits && context[0].fits->isValid() &&
- (context[0].fits->isImage() || context[0].fits->isCompress()) &&
+ (context[0].fits->isImage() || context[0].fits->isPost()) &&
context[1].fits && context[1].fits->isValid() &&
- (context[1].fits->isImage() || context[1].fits->isCompress()) &&
+ (context[1].fits->isImage() || context[1].fits->isPost()) &&
context[2].fits && context[2].fits->isValid() &&
- (context[2].fits->isImage() || context[2].fits->isCompress())) {
+ (context[2].fits->isImage() || context[2].fits->isPost())) {
loadRGBFinish();
return;
@@ -384,7 +384,7 @@ void FrameRGB::loadRGBImage(MemType which, const char* fn, FitsImage* img)
FitsImage* g = NULL;
FitsImage* b = NULL;
- if (!img || !img->isValid() || !(img->isImage() || img->isCompress()))
+ if (!img || !img->isValid() || !(img->isImage() || img->isPost()))
goto error;
switch (which) {
@@ -507,11 +507,11 @@ void FrameRGB::loadRGBImage(MemType which, const char* fn, FitsImage* img)
// is everything ok?
if (context[0].fits && context[0].fits->isValid() &&
- (context[0].fits->isImage() || context[0].fits->isCompress()) &&
+ (context[0].fits->isImage() || context[0].fits->isPost()) &&
context[1].fits && context[1].fits->isValid() &&
- (context[1].fits->isImage() || context[1].fits->isCompress()) &&
+ (context[1].fits->isImage() || context[1].fits->isPost()) &&
context[2].fits && context[2].fits->isValid() &&
- (context[2].fits->isImage() || context[2].fits->isCompress())) {
+ (context[2].fits->isImage() || context[2].fits->isPost())) {
loadRGBFinish();
return;
diff --git a/saotk/frame/framergbtruecolor.C b/saotk/frame/framergbtruecolor.C
index f99c461..2d11afb 100644
--- a/saotk/frame/framergbtruecolor.C
+++ b/saotk/frame/framergbtruecolor.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
diff --git a/saotk/frame/frametrue.C b/saotk/frame/frametrue.C
index e9836fd..f5dd617 100644
--- a/saotk/frame/frametrue.C
+++ b/saotk/frame/frametrue.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -41,13 +41,13 @@ void FrameTrue::rotateMotion()
int& width = options->width;
int& height = options->height;
- char* src = XImageData(rotateSrcXM);
+ char* src = rotateSrcXM->data;
int bytesPerPixel = rotateDestXM->bits_per_pixel/8;
for (int j=0; j<height; j++) {
// the line may be padded at the end
- char* dest = XImageData(rotateDestXM) + j*rotateDestXM->bytes_per_line;
+ char* dest = rotateDestXM->data + j*rotateDestXM->bytes_per_line;
for (int i=0; i<width; i++, dest+=bytesPerPixel) {
double x = i*mm[0] + j*mm[3] + mm[6];
diff --git a/saotk/frame/frametruecolor.C b/saotk/frame/frametruecolor.C
index a444108..ca72b9b 100644
--- a/saotk/frame/frametruecolor.C
+++ b/saotk/frame/frametruecolor.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -227,7 +227,7 @@ void FrameTrueColor::colormapMotionCmd(int id, float b, float c, int i,
// clear ximage
int& width = colormapXM->width;
int& height = colormapXM->height;
- char* data = XImageData(colormapXM);
+ char* data = colormapXM->data;
int bytesPerPixel = colormapXM->bits_per_pixel/8;
int& bytesPerLine = colormapXM->bytes_per_line;
diff --git a/saotk/frame/frblt.C b/saotk/frame/frblt.C
index 3795664..358f356 100644
--- a/saotk/frame/frblt.C
+++ b/saotk/frame/frblt.C
@@ -5,9 +5,11 @@
#include "base.h"
#include "context.h"
#include "fitsimage.h"
-#include "blt.h"
-#include "bltVector.h"
+
#include "projection.h"
+extern "C" {
+#include "bltVector.h"
+}
#include "sigbus.h"
@@ -127,38 +129,73 @@ int Base::markerAnalysisPlot3d(Marker* pp, double** x, double** y,
}
// init
- int cnt[srcd];
*x = (double*)malloc(srcd*sizeof(double));
*y = (double*)malloc(srcd*sizeof(double));
- for (long kk=0; kk<srcd; kk++) {
- (*x)[kk] = 0;
- (*y)[kk] = 0;
- cnt[kk] = 0;
- }
+ memset(*x,0,srcd*sizeof(double));
+ memset(*y,0,srcd*sizeof(double));
+
+ int* cnt = new int[srcd];
+ memset(cnt,0,srcd*sizeof(int));
// take the bbox and extend to lower/upper pixel boundaries
Vector ll = (bb.ll*ptr->refToData).floor();
Vector ur = (bb.ur*ptr->refToData).ceil();
+ // mask
+ int ss = (ur[0]-ll[0])*(ur[1]-ll[1]);
+ bool* msk = new bool[ss];
+ long* idx = new long[ss];
+ memset(msk,0,ss*sizeof(bool));
+ memset(idx,0,ss*sizeof(long));
+
+ bool* mptr=msk;
+ long* iptr=idx;
+ if (!pp->isFixed()) {
+ Matrix bck = pp->bckMatrix();
+ for (int jj=ll[1]; jj<ur[1]; jj++) {
+ for (int ii=ll[0]; ii<ur[0]; ii++,mptr++,iptr++) {
+ if (ii>=params->xmin && ii<params->xmax &&
+ jj>=params->ymin && jj<params->ymax) {
+ // shift to center of pixel in DATA
+ Vector rr = Vector(ii,jj)+Vector(.5,.5);
+ if (pp->isIn(rr*ptr->dataToRef,bck)) {
+ *mptr=1;
+ *iptr=long(jj)*srcw+long(ii);
+ }
+ }
+ }
+ }
+ }
+ else {
+ for (int jj=ll[1]; jj<ur[1]; jj++) {
+ for (int ii=ll[0]; ii<ur[0]; ii++,mptr++,iptr++) {
+ if (ii>=params->xmin && ii<params->xmax &&
+ jj>=params->ymin && jj<params->ymax) {
+ // shift to center of pixel in DATA
+ Vector rr = Vector(ii,jj)+Vector(.5,.5);
+ if (pp->isIn(rr*ptr->dataToRef,Coord::REF)) {
+ *mptr=1;
+ *iptr=long(jj)*srcw+long(ii);
+ }
+ }
+ }
+ }
+ }
+
// main loop
SETSIGBUS
for (int kk=0; kk<srcd; kk++) {
(*x)[kk] = ptr->mapFromRef3(kk+.5+params->zmin, sys, 2);
- for (int jj=ll[1]; jj<ur[1]; jj++) {
- for (int ii=ll[0]; ii<ur[0]; ii++) {
- if (ii>=params->xmin && ii<params->xmax &&
- jj>=params->ymin && jj<params->ymax) {
- // shift to center of pixel in DATA
- Vector rr = Vector(ii,jj)+Vector(.5,.5);
- if (pp->isIn(rr*ptr->dataToRef,Coord::REF)) {
- double val =sjv[kk]->getValueDouble(long(jj)*srcw+long(ii));
- // check for nan
- if (isfinite(val)) {
- (*y)[kk] += val;
- cnt[kk]++;
- }
- }
+ bool* mptr=msk;
+ long* iptr=idx;
+ for (int ll=0; ll<ss; ll++,mptr++,iptr++) {
+ if (*mptr) {
+ double val =sjv[kk]->getValueDouble(*iptr);
+ // check for nan
+ if (isfinite(val)) {
+ (*y)[kk] += val;
+ cnt[kk]++;
}
}
}
@@ -171,6 +208,13 @@ int Base::markerAnalysisPlot3d(Marker* pp, double** x, double** y,
if (cnt[kk]!=0)
(*y)[kk] /= cnt[kk];
+ if (cnt)
+ delete [] cnt;
+ if (msk)
+ delete [] msk;
+ if (idx)
+ delete [] idx;
+
return srcd;
}
diff --git a/saotk/frame/frcommand.C b/saotk/frame/frcommand.C
index c178f79..4e4d3f3 100644
--- a/saotk/frame/frcommand.C
+++ b/saotk/frame/frcommand.C
@@ -5,7 +5,7 @@
#include <fstream>
#include "fdstream.hpp"
-#include "tcl.h"
+#include <tk.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
diff --git a/saotk/frame/grid.h b/saotk/frame/grid.h
index 4bd978b..bfe4286 100644
--- a/saotk/frame/grid.h
+++ b/saotk/frame/grid.h
@@ -5,8 +5,6 @@
#ifndef __grid_h__
#define __grid_h__
-#include <tk.h>
-
#include "coord.h"
class Grid {
diff --git a/saotk/frame/grid25d.h b/saotk/frame/grid25d.h
index e706a5f..ce3dca5 100644
--- a/saotk/frame/grid25d.h
+++ b/saotk/frame/grid25d.h
@@ -5,8 +5,6 @@
#ifndef __grid25d_h__
#define __grid25d_h__
-#include <tk.h>
-
#include "grid.h"
#include "grid25dbase.h"
#include "coord.h"
diff --git a/saotk/frame/grid2d.h b/saotk/frame/grid2d.h
index 7d1941d..b540ebc 100644
--- a/saotk/frame/grid2d.h
+++ b/saotk/frame/grid2d.h
@@ -5,8 +5,6 @@
#ifndef __grid2d_h__
#define __grid2d_h__
-#include <tk.h>
-
#include "grid.h"
#include "grid2dbase.h"
#include "coord.h"
diff --git a/saotk/frame/grid3d.h b/saotk/frame/grid3d.h
index f6a5820..9a47484 100644
--- a/saotk/frame/grid3d.h
+++ b/saotk/frame/grid3d.h
@@ -5,8 +5,6 @@
#ifndef __grid3d_h__
#define __grid3d_h__
-#include <tk.h>
-
#include "grid.h"
#include "grid3dbase.h"
#include "coord.h"
diff --git a/saotk/frame/line.C b/saotk/frame/line.C
index ef5cff1..01084d0 100644
--- a/saotk/frame/line.C
+++ b/saotk/frame/line.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "line.h"
#include "fitsimage.h"
diff --git a/saotk/frame/marker.C b/saotk/frame/marker.C
index e780ed8..257f6d7 100644
--- a/saotk/frame/marker.C
+++ b/saotk/frame/marker.C
@@ -2,10 +2,14 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "marker.h"
#include "fitsimage.h"
-#include "blt.h"
+
+extern "C" {
#include "bltVector.h"
+}
static int markerSeqID = 1;
@@ -479,7 +483,7 @@ void Marker::renderMACOSXText()
}
void Marker::renderMACOSXArrow(const Vector& p1, const Vector& p2,
- InternalSystem sys)
+ Coord::InternalSystem sys)
{
Vector* vv = arrow(p1,p2,sys);
Vector dd[6];
@@ -1051,6 +1055,13 @@ int Marker::isIn(const Vector& vv, Coord::InternalSystem sys)
return bbox.isIn(ss);
}
+// assume Coord::REF
+int Marker::isIn(const Vector& vv, const Matrix& bck)
+{
+ Vector ss = parent->mapFromRef(vv,Coord::CANVAS);
+ return bbox.isIn(ss);
+}
+
int Marker::isVisible(const BBox& b)
{
// assume visible, prove otherwise
diff --git a/saotk/frame/marker.h b/saotk/frame/marker.h
index 8206f82..0a798f9 100644
--- a/saotk/frame/marker.h
+++ b/saotk/frame/marker.h
@@ -166,11 +166,6 @@ protected:
void listProps(ostream&);
void listProperties(ostream&, int);
- virtual Matrix fwdMatrix();
- virtual Matrix bckMatrix();
- virtual Vector fwdMap(const Vector&, Coord::InternalSystem);
- virtual Vector bckMap(const Vector&, Coord::InternalSystem);
-
void XMLRowInit();
void XMLRow(XMLColName,int);
void XMLRow(XMLColName,int*,int);
@@ -201,6 +196,11 @@ protected:
const List<Tag>& tag, const List<CallBack>& cb);
virtual ~Marker();
+ virtual Matrix fwdMatrix();
+ virtual Matrix bckMatrix();
+ virtual Vector fwdMap(const Vector&, Coord::InternalSystem);
+ virtual Vector bckMap(const Vector&, Coord::InternalSystem);
+
virtual void x11(Drawable, Coord::InternalSystem, int, RenderMode,HandleMode);
virtual void ps(int,int);
#ifdef _MACOSX
@@ -232,13 +232,22 @@ protected:
virtual void rotate(const Vector& v, int h);
virtual void rotateEnd();
+ // assume Coord::CANVAS
virtual int isIn(const Vector& vv) {return bbox.isIn(vv);}
+
virtual int isIn(const Vector& vv, Coord::InternalSystem sys);
virtual int isIn(const Vector& vv, Coord::InternalSystem sys, int nn)
{return isIn(vv,sys);}
virtual int isIn(const Vector& vv, Coord::InternalSystem sys, int nn, int aa)
{return isIn(vv,sys);}
+ // assume Coord::REF
+ virtual int isIn(const Vector& vv, const Matrix& bck);
+ virtual int isIn(const Vector& vv, const Matrix& bck, int nn)
+ {return isIn(vv,bck);}
+ virtual int isIn(const Vector& vv, const Matrix& bck, int nn, int aa)
+ {return isIn(vv,bck);}
+
void setAngle(double);
double getAngle() {return angle;}
diff --git a/saotk/frame/point.C b/saotk/frame/point.C
index 93c0474..1d44bac 100644
--- a/saotk/frame/point.C
+++ b/saotk/frame/point.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "point.h"
#include "fitsimage.h"
@@ -260,6 +262,7 @@ void Point::renderPSLineDash()
void Point::renderMACOSX()
{
renderMACOSXGC();
+ Vector* vv = NULL;
switch (shape_) {
case CIRCLE:
@@ -692,9 +695,9 @@ void Point::analysisPlot3d(char* xname, char* yname,
analysisPlot3dResult(xname, yname, x, y, num);
}
-int Point::isIn(const Vector& vv, Coord::InternalSystem sys)
+int Point::isInRef(const Vector& vv)
{
- Vector pp = bckMap(vv,sys);
+ Vector& pp = (Vector&)vv;
if (pp[0]<-.5 || pp[0]>=.5 || pp[1]<-.5 || pp[1]>=.5)
return 0;
diff --git a/saotk/frame/point.h b/saotk/frame/point.h
index 3ba5c0e..73b8021 100644
--- a/saotk/frame/point.h
+++ b/saotk/frame/point.h
@@ -46,6 +46,8 @@ class Point : public Marker {
void shapeStr(PointShape);
void updateHandles();
+ int isInRef(const Vector&);
+
public:
Point(const Point&);
Point(Base* p, const Vector& ctr,
@@ -75,8 +77,6 @@ class Point : public Marker {
int size() {return size_;}
void setSize(int);
- int isIn(const Vector&, Coord::InternalSystem);
-
void editBegin(int) {}
void edit(const Vector& v, int h) {}
void editEnd() {}
@@ -89,6 +89,11 @@ class Point : public Marker {
void analysisPlot3d(char*, char*, Coord::CoordSystem sys,
Marker::AnalysisMethod);
+ int isIn(const Vector& vv, Coord::InternalSystem sys)
+ {return isInRef(bckMap(vv,sys));}
+ int isIn(const Vector& vv, const Matrix& bck)
+ {return isInRef(vv*bck);}
+
void list(ostream&, Coord::CoordSystem, Coord::SkyFrame, Coord::SkyFormat, int, int);
void listXML(ostream&, Coord::CoordSystem, Coord::SkyFrame, Coord::SkyFormat);
void listPost(ostream&, int, int);
diff --git a/saotk/frame/polygon.C b/saotk/frame/polygon.C
index 48a7674..789683d 100644
--- a/saotk/frame/polygon.C
+++ b/saotk/frame/polygon.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "polygon.h"
#include "fitsimage.h"
@@ -257,7 +259,7 @@ void Polygon::reset(const Vector& b)
updateBBox();
}
-int Polygon::isIn(const Vector& vv, Coord::InternalSystem sys)
+int Polygon::isInRef(const Vector& v)
{
/*
v[0]-- x value of point being tested
@@ -273,7 +275,6 @@ int Polygon::isIn(const Vector& vv, Coord::InternalSystem sys)
Points on a edge are considered inside.
*/
- Vector v = bckMap(vv,sys);
int crossings = 0; // number of crossings
vertex.head();
diff --git a/saotk/frame/polygon.h b/saotk/frame/polygon.h
index bca52a3..457db75 100644
--- a/saotk/frame/polygon.h
+++ b/saotk/frame/polygon.h
@@ -26,6 +26,8 @@ class Polygon : public Marker {
void moveVertex(const Vector&, int);
void recalcCenter();
+ int isInRef(const Vector& v);
+
public:
Polygon(const Polygon&);
Polygon(Base* p, const Vector& ctr,
@@ -46,9 +48,6 @@ public:
void edit(const Vector&, int);
void rotate(const Vector&, int);
- int isIn(const Vector& vv) {return isIn(vv, Coord::CANVAS);}
- int isIn(const Vector&, Coord::InternalSystem);
-
void analysis(AnalysisTask, int);
void analysisPlot3d(char*, char*, Coord::CoordSystem, Marker::AnalysisMethod);
void analysisStats(Coord::CoordSystem);
@@ -58,6 +57,13 @@ public:
int getSegment(const Vector&);
void reset(const Vector&);
+ int isIn(const Vector& vv) {return isIn(vv, Coord::CANVAS);}
+ int isIn(const Vector& vv, Coord::InternalSystem sys)
+ {return isInRef(bckMap(vv,sys));}
+
+ int isIn(const Vector& vv, const Matrix& bck)
+ {return isInRef(vv*bck);}
+
void list(ostream&, Coord::CoordSystem, Coord::SkyFrame, Coord::SkyFormat, int, int);
void listXML(ostream&, Coord::CoordSystem, Coord::SkyFrame, Coord::SkyFormat);
virtual void listCiao(ostream&, Coord::CoordSystem, int);
diff --git a/saotk/frame/projection.C b/saotk/frame/projection.C
index 317a95d..ad8478f 100644
--- a/saotk/frame/projection.C
+++ b/saotk/frame/projection.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "projection.h"
#include "fitsimage.h"
diff --git a/saotk/frame/ruler.C b/saotk/frame/ruler.C
index 53f9409..9f75e8c 100644
--- a/saotk/frame/ruler.C
+++ b/saotk/frame/ruler.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "ruler.h"
#include "fitsimage.h"
@@ -204,7 +206,7 @@ void Ruler::renderMACOSX()
Tk_FontMetrics metrics;
Tk_GetFontMetrics(psfont_, &metrics);
char* buf = dupstr(vstr.str().c_str());
- int width = Tk_TextWidth(psfont_, vbuf, strlen(buf));
+ int width = Tk_TextWidth(psfont_, buf, strlen(buf));
Vector tt = ((bb-aa)/2 + aa) * Translate(-width/2., -metrics.descent);
macosxDrawText(tt, 0, buf);
diff --git a/saotk/frame/segment.C b/saotk/frame/segment.C
index 5476b7d..a3a4421 100644
--- a/saotk/frame/segment.C
+++ b/saotk/frame/segment.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "segment.h"
#include "fitsimage.h"
diff --git a/saotk/frame/text.C b/saotk/frame/text.C
index 6701d4f..0f68ece 100644
--- a/saotk/frame/text.C
+++ b/saotk/frame/text.C
@@ -2,14 +2,12 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "text.h"
#include "fitsimage.h"
#include "rotstr.h"
-#include <tcl.h>
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
Text::Text(const Text& a) : Marker(a)
{
rotate = a.rotate;
@@ -51,9 +49,13 @@ void Text::renderX(Drawable drawable, Coord::InternalSystem sys, RenderMode mode
Translate(cc);
Vector vv = cc * mm;
-#if !(_GWIN32 || _MACOSX)
+#if !(_MACOSX || _GWIN32)
XDrawRotString(display, drawable, lgc, vv, ang, text, tkfont_, parent);
-#else
+#endif
+#ifdef _MACOSX
+ XDrawRotString(display, drawable, lgc, vv, ang, text, tkfont_);
+#endif
+#ifdef _GWIN32
XDrawRotString(display, drawable, lgc, vv, ang, text);
#endif
}
diff --git a/saotk/frame/vect.C b/saotk/frame/vect.C
index 31b40d5..d753051 100644
--- a/saotk/frame/vect.C
+++ b/saotk/frame/vect.C
@@ -2,6 +2,8 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "vect.h"
#include "fitsimage.h"
diff --git a/saotk/list/Makefile b/saotk/list/Makefile
index bc4f3ec..379ab39 100644
--- a/saotk/list/Makefile
+++ b/saotk/list/Makefile
@@ -8,28 +8,12 @@ SRC = list.C
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o $(LIB)
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o $(LIB)
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/magnifier/Makefile b/saotk/magnifier/Makefile
index 32aa0c1..7ba2c78 100644
--- a/saotk/magnifier/Makefile
+++ b/saotk/magnifier/Makefile
@@ -4,36 +4,22 @@ CXXFLAGS = $(CXXOPT) \
-I. -I.. -I../widget -I../vector -I../util \
-I../../include -I$(X11INCLUDE)
-SS = \
+SRC = \
magnifier.C \
- magnifiertrue.C
-
-ifeq ($(OS),unix)
-SSP = \
- magnifierpseudo.C
-endif
-
-SRC = $(SS) $(SSP) \
+ magnifiertrue.C \
parser.C \
lex.C
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o $(LIB) parser.output
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o $(LIB) parser.output
parsers : parser
@@ -42,12 +28,3 @@ parser : FORCE
flex -Pmg -olex.C lex.L
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/magnifier/magnifierpseudo.C b/saotk/magnifier/magnifierpseudo.C
deleted file mode 100644
index 9333e76..0000000
--- a/saotk/magnifier/magnifierpseudo.C
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "magnifierpseudo.h"
-
-// Tk Canvas Widget Function Declarations
-
-int MagnifierPseudoColorCreateProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int,
- Tcl_Obj *const []);
-
-// MagnifierPseudoColor Specs
-
-static Tk_CustomOption tagsOption = {
- Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
-};
-
-static Tk_ConfigSpec magnifierPseudoColorSpecs[] = {
-
- {TK_CONFIG_STRING, (char*)"-command", NULL, NULL, "magnifier",
- Tk_Offset(WidgetOptions, cmdName), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-x", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, x), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-y", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, y), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-width", NULL, NULL, "256",
- Tk_Offset(WidgetOptions, width), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-height", NULL, NULL, "256",
- Tk_Offset(WidgetOptions, height), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_ANCHOR, (char*)"-anchor", NULL, NULL, "nw",
- Tk_Offset(WidgetOptions, anchor), 0, NULL},
- {TK_CONFIG_CUSTOM, (char*)"-tags", NULL, NULL, NULL,
- 0, TK_CONFIG_NULL_OK, &tagsOption},
-
- {TK_CONFIG_STRING, (char*)"-helvetica", NULL, NULL, "helvetica",
- Tk_Offset(WidgetOptions, helvetica), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-courier", NULL, NULL, "courier",
- Tk_Offset(WidgetOptions, courier), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-times", NULL, NULL, "times",
- Tk_Offset(WidgetOptions, times), 0, NULL},
-
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL},
-};
-
-// Tk Static Structure
-
-static Tk_ItemType magnifierPseudoColorType = {
- (char*)"magnifierpseudocolor", // name
- sizeof(WidgetOptions), // size
- MagnifierPseudoColorCreateProc, // configProc
- magnifierPseudoColorSpecs, // configSpecs
- WidgetConfigProc, // configProc
- WidgetCoordProc, // coordProc
- WidgetDeleteProc, // deleteProc
- WidgetDisplayProc, // displayProc
- 0, // alwaysRedraw
- WidgetPointProc, // pointProc
- WidgetAreaProc, // areaProc
- WidgetPostscriptProc, // postscriptProc
- WidgetScaleProc, // scaleProc
- WidgetTranslateProc, // translateProc
- (Tk_ItemIndexProc*)NULL, // indexProc
- (Tk_ItemCursorProc*)NULL, // icursorProc
- (Tk_ItemSelectionProc*)NULL, // selectionProc
- (Tk_ItemInsertProc*)NULL, // insertProc
- (Tk_ItemDCharsProc*)NULL, // dCharsProc
- (Tk_ItemType*)NULL // nextPtr
-};
-
-// Non-Member Functions
-
-int MagnifierPseudoColor_Init(Tcl_Interp* interp)
-{
- Tk_CreateItemType(&magnifierPseudoColorType);
- return TCL_OK;
-}
-
-int MagnifierPseudoColorCreateProc(Tcl_Interp* interp, Tk_Canvas canvas,
- Tk_Item* item,
- int argc, Tcl_Obj *const argv[])
-{
- MagnifierPseudoColor* magnifier =
- new MagnifierPseudoColor(interp, canvas, item);
-
- // and set default configuration
-
- if (magnifier->configure(argc, (const char**)argv, 0) != TCL_OK) {
- delete magnifier;
- Tcl_AppendResult(interp, " error occured while creating magnifier.", NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-MagnifierPseudoColor::MagnifierPseudoColor(Tcl_Interp* i, Tk_Canvas c,
- Tk_Item* item)
- : Magnifier(i, c, item)
-{
- configSpecs = magnifierPseudoColorSpecs; // magnifier configure options
-}
-
-void MagnifierPseudoColor::clearPixmap()
-{
- XSetForeground(display, gc, getColor("white"));
- XFillRectangle(display, pixmap, gc, 0, 0, options->width, options->height);
-}
diff --git a/saotk/magnifier/magnifierpseudo.h b/saotk/magnifier/magnifierpseudo.h
deleted file mode 100644
index 2ee950a..0000000
--- a/saotk/magnifier/magnifierpseudo.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __magnifierpseudo_h__
-#define __magnifierpseudo_h__
-
-#include "magnifier.h"
-
-class MagnifierPseudoColor : public Magnifier {
-private:
- void clearPixmap();
-
-public:
- MagnifierPseudoColor(Tcl_Interp*, Tk_Canvas, Tk_Item*);
-};
-
-#endif
diff --git a/saotk/magnifier/magnifiertrue.C b/saotk/magnifier/magnifiertrue.C
index 961e5ef..4683703 100644
--- a/saotk/magnifier/magnifiertrue.C
+++ b/saotk/magnifier/magnifiertrue.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -111,7 +111,7 @@ void MagnifierTrueColor::clearPixmap()
return;
}
- memset(XImageData(xmap), 255, xmap->bytes_per_line * xmap->height);
+ memset(xmap->data, 255, xmap->bytes_per_line * xmap->height);
XPutImage(display, pixmap, gc, xmap, 0, 0, 0, 0, options->width,
options->height);
diff --git a/saotk/panner/Makefile b/saotk/panner/Makefile
index 894dc36..8a02ec4 100644
--- a/saotk/panner/Makefile
+++ b/saotk/panner/Makefile
@@ -4,32 +4,22 @@ CXXFLAGS = $(CXXOPT) \
-I. -I.. -I../widget -I../vector -I../util \
-I../../include -I$(X11INCLUDE)
-SS = \
+SRC = \
panner.C \
- pannerpseudo.C \
- pannertrue.C
-
-SRC = $(SS) \
+ pannertrue.C \
parser.C \
lex.C
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o $(LIB) parser.output
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o $(LIB) parser.output
parsers : parser
@@ -38,12 +28,3 @@ parser : FORCE
flex -Ppn -olex.C lex.L
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/panner/panner.C b/saotk/panner/panner.C
index 57e9fbb..f74e58f 100644
--- a/saotk/panner/panner.C
+++ b/saotk/panner/panner.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
+#include <tcl.h>
#include <X11/Xlib.h>
#include "panner.h"
diff --git a/saotk/panner/pannerpseudo.C b/saotk/panner/pannerpseudo.C
deleted file mode 100644
index dbe54f7..0000000
--- a/saotk/panner/pannerpseudo.C
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#include "pannerpseudo.h"
-
-// Tk Canvas Widget Function Declarations
-
-int PannerPseudoColorCreateProc(Tcl_Interp*, Tk_Canvas, Tk_Item*, int,
- Tcl_Obj *const []);
-
-// PannerPseudoColor Specs
-
-static Tk_CustomOption tagsOption = {
- Tk_CanvasTagsParseProc, Tk_CanvasTagsPrintProc, NULL
-};
-
-static Tk_ConfigSpec pannerPseudoColorSpecs[] = {
-
- {TK_CONFIG_STRING, (char*)"-command", NULL, NULL, "panner",
- Tk_Offset(WidgetOptions, cmdName), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-x", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, x), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-y", NULL, NULL, "1",
- Tk_Offset(WidgetOptions, y), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-width", NULL, NULL, "256",
- Tk_Offset(WidgetOptions, width), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_INT, (char*)"-height", NULL, NULL, "256",
- Tk_Offset(WidgetOptions, height), TK_CONFIG_OPTION_SPECIFIED, NULL},
- {TK_CONFIG_ANCHOR, (char*)"-anchor", NULL, NULL, "nw",
- Tk_Offset(WidgetOptions, anchor), 0, NULL},
- {TK_CONFIG_CUSTOM, (char*)"-tags", NULL, NULL, NULL,
- 0, TK_CONFIG_NULL_OK, &tagsOption},
-
- {TK_CONFIG_STRING, (char*)"-helvetica", NULL, NULL, "helvetica",
- Tk_Offset(WidgetOptions, helvetica), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-courier", NULL, NULL, "courier",
- Tk_Offset(WidgetOptions, courier), 0, NULL},
- {TK_CONFIG_STRING, (char*)"-times", NULL, NULL, "times",
- Tk_Offset(WidgetOptions, times), 0, NULL},
-
- {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL},
-};
-
-// Tk Static Structure
-
-static Tk_ItemType pannerPseudoColorType = {
- (char*)"pannerpseudocolor", // name
- sizeof(WidgetOptions), // size
- PannerPseudoColorCreateProc, // configProc
- pannerPseudoColorSpecs, // configSpecs
- WidgetConfigProc, // configProc
- WidgetCoordProc, // coordProc
- WidgetDeleteProc, // deleteProc
- WidgetDisplayProc, // displayProc
- 0, // alwaysRedraw
- WidgetPointProc, // pointProc
- WidgetAreaProc, // areaProc
- WidgetPostscriptProc, // postscriptProc
- WidgetScaleProc, // scaleProc
- WidgetTranslateProc, // translateProc
- (Tk_ItemIndexProc*)NULL, // indexProc
- WidgetICursorProc, // icursorProc
- (Tk_ItemSelectionProc*)NULL, // selectionProc
- (Tk_ItemInsertProc*)NULL, // insertProc
- (Tk_ItemDCharsProc*)NULL, // dCharsProc
- (Tk_ItemType*)NULL // nextPtr
-};
-
-// Non-Member Functions
-
-int PannerPseudoColor_Init(Tcl_Interp* interp)
-{
- Tk_CreateItemType(&pannerPseudoColorType);
- return TCL_OK;
-}
-
-int PannerPseudoColorCreateProc(Tcl_Interp* interp, Tk_Canvas canvas,
- Tk_Item* item, int argc, Tcl_Obj *const argv[])
-{
- PannerPseudoColor* panner = new PannerPseudoColor(interp, canvas, item);
-
- // and set default configuration
-
- if (panner->configure(argc, (const char**)argv, 0) != TCL_OK) {
- delete panner;
- Tcl_AppendResult(interp,
- " error occured while creating pannerPseudoColor.", NULL);
- return TCL_ERROR;
- }
-
- return TCL_OK;
-}
-
-PannerPseudoColor::PannerPseudoColor(Tcl_Interp* i, Tk_Canvas c,
- Tk_Item* item) : Panner(i, c, item)
-{
- configSpecs = pannerPseudoColorSpecs; // panner configure options
-}
-
-void PannerPseudoColor::clearPixmap()
-{
- XFillRectangle(display, pixmap, gc, 0, 0, options->width, options->height);
-}
diff --git a/saotk/panner/pannerpseudo.h b/saotk/panner/pannerpseudo.h
deleted file mode 100644
index e8a2738..0000000
--- a/saotk/panner/pannerpseudo.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (C) 1999-2012
-// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
-// For conditions of distribution and use, see copyright notice in "copyright"
-
-#ifndef __pannerpseudo_h__
-#define __pannerpseudo_h__
-
-#include "panner.h"
-
-class PannerPseudoColor : public Panner {
-private:
- void clearPixmap();
-
-public:
- PannerPseudoColor(Tcl_Interp*, Tk_Canvas, Tk_Item*);
-};
-
-#endif
-
diff --git a/saotk/panner/pannertrue.C b/saotk/panner/pannertrue.C
index e3b10d6..4edbbf8 100644
--- a/saotk/panner/pannertrue.C
+++ b/saotk/panner/pannertrue.C
@@ -2,8 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tcl.h"
-
+#include <tcl.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -114,7 +113,7 @@ void PannerTrueColor::clearPixmap()
return;
}
- memset(XImageData(xmap), 255, xmap->bytes_per_line * xmap->height);
+ memset(xmap->data, 255, xmap->bytes_per_line * xmap->height);
XPutImage(display, pixmap, gc, xmap, 0, 0, 0, 0, options->width, options->height);
XDestroyImage(xmap);
diff --git a/saotk/util/Makefile b/saotk/util/Makefile
index 592572c..09f5ec8 100644
--- a/saotk/util/Makefile
+++ b/saotk/util/Makefile
@@ -24,28 +24,12 @@ INCLS = smooth.h \
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/util/grid25dbase.h b/saotk/util/grid25dbase.h
index cf79594..aacca74 100644
--- a/saotk/util/grid25dbase.h
+++ b/saotk/util/grid25dbase.h
@@ -5,8 +5,6 @@
#ifndef __grid25dbase_h__
#define __grid25dbase_h__
-#include <tk.h>
-
#include "gridbase.h"
class Grid25dBase : public GridBase {
diff --git a/saotk/util/grid2dbase.h b/saotk/util/grid2dbase.h
index 26b38e1..a551773 100644
--- a/saotk/util/grid2dbase.h
+++ b/saotk/util/grid2dbase.h
@@ -5,8 +5,6 @@
#ifndef __grid2dbase_h__
#define __grid2dbase_h__
-#include <tk.h>
-
#include "gridbase.h"
class Grid2dBase : public GridBase {
diff --git a/saotk/util/gridbase.C b/saotk/util/gridbase.C
index 96b3cc8..0803830 100644
--- a/saotk/util/gridbase.C
+++ b/saotk/util/gridbase.C
@@ -175,10 +175,15 @@ int GridBase::x11Text(const char* txt, float x, float y,
double angle = calcTextAngle(just, up);
Vector cc = vv * calcTextPos(vv, angle, txt, just, up, text_->tkfont());
-#if !(_GWIN32 || _MACOSX)
+#if !(_MACOSX || _GWIN32)
XDrawRotString(parent_->getDisplay(), pixmap_, gc_, cc, angle, txt,
text_->tkfont(), parent_);
-#else
+#endif
+#ifdef _MACOSX
+ XDrawRotString(parent_->getDisplay(), pixmap_, gc_, cc, angle, txt,
+ text_->tkfont());
+#endif
+#ifdef _GWIN32
XDrawRotString(parent_->getDisplay(), pixmap_, gc_, cc, angle, txt);
#endif
return 1;
diff --git a/saotk/util/saotk.C b/saotk/util/saotk.C
index ee6a955..0ab3dda 100644
--- a/saotk/util/saotk.C
+++ b/saotk/util/saotk.C
@@ -2,7 +2,7 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
-#include "tk.h"
+#include <tcl.h>
extern int FrameTrueColor8_Init(Tcl_Interp*);
extern int FrameTrueColor16_Init(Tcl_Interp*);
@@ -28,13 +28,6 @@ extern int PannerTrueColor_Init(Tcl_Interp*);
extern int MagnifierTrueColor_Init(Tcl_Interp*);
-#if !(_GWIN32 || _MACOSX)
-extern int FramePseudoColor8_Init(Tcl_Interp*);
-extern int ColorbarPseudoColor8_Init(Tcl_Interp*);
-extern int MagnifierPseudoColor_Init(Tcl_Interp*);
-extern int PannerPseudoColor_Init(Tcl_Interp*);
-#endif
-
extern "C" {
int Saotk_Init(Tcl_Interp* interp);
int SaotkCmd(ClientData data, Tcl_Interp *interp, int argc,
@@ -85,18 +78,6 @@ int Saotk_Init(Tcl_Interp* interp) {
if (ColorbarRGBTrueColor24_Init(interp) == TCL_ERROR)
return TCL_ERROR;
- // PseudoColor
-#if !(_GWIN32 || _MACOSX)
- if (FramePseudoColor8_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- if (ColorbarPseudoColor8_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- if (PannerPseudoColor_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
- if (MagnifierPseudoColor_Init(interp) == TCL_ERROR)
- return TCL_ERROR;
-#endif
-
// dummy command
// needed for auto_load, since all of our real work are canvas widgets,
// tcl commands
diff --git a/saotk/util/util.C b/saotk/util/util.C
index 8a44002..341887d 100644
--- a/saotk/util/util.C
+++ b/saotk/util/util.C
@@ -4,10 +4,6 @@
#include "util.h"
-#ifdef _MACOSX
-void macosxGetMasks(long*,long*,long*);
-#endif
-
// Error in mapping
int maperr= 0;
diff --git a/saotk/util/util.h b/saotk/util/util.h
index 053264d..ac525f5 100644
--- a/saotk/util/util.h
+++ b/saotk/util/util.h
@@ -16,6 +16,9 @@
#include <iomanip>
using namespace std;
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
#include "fuzzy.h"
#include "vector.h"
@@ -23,8 +26,6 @@ using namespace std;
#define PATH_MAX 1024
#endif
-#define XImageData(x) x->data
-
#ifdef _GWIN32
#include <xxlib.h>
#include <win32lib.h>
@@ -33,10 +34,8 @@ using namespace std;
#endif
#ifdef _MACOSX
-#undef XImageData
#include <xxlib.h>
#include <macosxlib.h>
-#define XGetImage XXGetImage
#define XQueryPointer XXQueryPointer
#define XWarpPointer XXWarpPointer
#endif
@@ -118,8 +117,4 @@ extern int dCompare(const void*, const void*);
extern Vector mapLen(const Vector& v, const Matrix& mx);
-extern "C" {
-extern void conputs(FILE *fd, char *format, ...);
-}
-
#endif
diff --git a/saotk/vector/Makefile b/saotk/vector/Makefile
index 24c43cd..9851f55 100644
--- a/saotk/vector/Makefile
+++ b/saotk/vector/Makefile
@@ -7,28 +7,12 @@ SRC = vector.C vector3d.C
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o $(LIB)
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o $(LIB)
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/vector/vector.C b/saotk/vector/vector.C
index 07b8d2c..4d5fc60 100644
--- a/saotk/vector/vector.C
+++ b/saotk/vector/vector.C
@@ -2,9 +2,10 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "vector.h"
#include "vector3d.h"
-
#include "fuzzy.h"
// Vector
@@ -39,6 +40,11 @@ Vector& Vector::clip(const BBox& bb)
return *this;
}
+Vector Vector::TkCanvasPs(void* canvas)
+{
+ return Vector(v[0], Tk_CanvasPsY((Tk_Canvas)canvas, v[1]));
+}
+
ostream& operator<<(ostream& s, const Vector& v)
{
s << ' ' << v.v[0] << ' ' << v.v[1] << ' ';
diff --git a/saotk/vector/vector.h b/saotk/vector/vector.h
index c48c503..4ace2bc 100644
--- a/saotk/vector/vector.h
+++ b/saotk/vector/vector.h
@@ -11,8 +11,6 @@
#include <iostream>
using namespace std;
-#include "tk.h"
-
class Vector3d;
class Matrix;
class BBox;
@@ -71,8 +69,7 @@ class Vector {
return d ? Vector(v[0]/d,v[1]/d) : Vector();}
Vector& clip(const BBox&);
- Vector TkCanvasPs(Tk_Canvas canvas)
- {return Vector(v[0], Tk_CanvasPsY(canvas, v[1]));}
+ Vector TkCanvasPs(void* canvas);
};
ostream& operator<<(ostream&, const Vector&);
istream& operator>>(istream&, Vector&);
@@ -310,7 +307,6 @@ inline BBox operator-(const BBox& b, const Vector& v) {return BBox(b) -= v;}
inline BBox operator*(const BBox& b, const Matrix& m) {return BBox(b) *= m;}
BBox intersect(const BBox&, const BBox&);
-
#endif
diff --git a/saotk/vector/vector3d.C b/saotk/vector/vector3d.C
index 1e18e2c..cb2837c 100644
--- a/saotk/vector/vector3d.C
+++ b/saotk/vector/vector3d.C
@@ -2,9 +2,10 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <tk.h>
+
#include "vector3d.h"
#include "vector.h"
-
#include "fuzzy.h"
// Vector3d
@@ -34,9 +35,9 @@ Vector3d& Vector3d::operator=(const Vector& a)
return *this;
}
-Vector Vector3d::TkCanvasPs(Tk_Canvas canvas)
+Vector Vector3d::TkCanvasPs(void* canvas)
{
- return Vector(v[0], Tk_CanvasPsY(canvas, v[1]));
+ return Vector(v[0], Tk_CanvasPsY((Tk_Canvas)canvas, v[1]));
}
ostream& operator<<(ostream& s, const Vector3d& v)
diff --git a/saotk/vector/vector3d.h b/saotk/vector/vector3d.h
index 22ad908..68c474e 100644
--- a/saotk/vector/vector3d.h
+++ b/saotk/vector/vector3d.h
@@ -11,8 +11,6 @@
#include <iostream>
using namespace std;
-#include "tk.h"
-
class Vector;
class Matrix;
class Matrix3d;
@@ -76,7 +74,7 @@ class Vector3d {
return d ? Vector3d(v[0]/d,v[1]/d,v[2]/d) : Vector3d();}
Vector3d project()
{return (v[3]!=1) ? Vector3d(v[0]/v[3],v[1]/v[3],v[2]/v[3]) : *this;}
- Vector TkCanvasPs(Tk_Canvas canvas);
+ Vector TkCanvasPs(void* canvas);
};
ostream& operator<<(ostream&, const Vector3d&);
istream& operator>>(istream&, Vector3d&);
diff --git a/saotk/vector/vectorold.h b/saotk/vector/vectorold.h
index feadd2a..1dffa48 100644
--- a/saotk/vector/vectorold.h
+++ b/saotk/vector/vectorold.h
@@ -11,7 +11,7 @@
#include <iostream>
using namespace std;
-#include "tk.h"
+#include <tk.h>
class Vector;
class Vertex;
diff --git a/saotk/widget/Makefile b/saotk/widget/Makefile
index ecde084..4cd3ff9 100644
--- a/saotk/widget/Makefile
+++ b/saotk/widget/Makefile
@@ -12,28 +12,12 @@ SRC = truecolor8.C \
INCLS = $(wildcard *.h)
OBJS = $(SRC:%.C=%.o)
-all : $(OBJS) TAGS
+all : $(OBJS)
clean : FORCE
rm -f core *~ *#
distclean : clean
- rm -f TAGS *.o $(LIB)
-
-ifdef DEPENDS
-TAGS : $(SS) $(INCLS)
- etags $+
-else
-TAGS : FORCE
-endif
+ rm -f *.o $(LIB)
FORCE:
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/saotk/widget/truecolor16.C b/saotk/widget/truecolor16.C
index b2dd665..34adabf 100644
--- a/saotk/widget/truecolor16.C
+++ b/saotk/widget/truecolor16.C
@@ -5,27 +5,13 @@
#include "truecolor16.h"
#include "util.h"
-#ifdef _MACOSX
-extern void macosxGetMasks(unsigned long*, unsigned long*,
- unsigned long*, unsigned long*);
-#endif
-
TrueColor16::TrueColor16(Visual* visual)
{
-#if !(_WIN32 || _MACOSX)
+#if !(_WIN32)
rx_ = visual->red_mask;
gx_ = visual->green_mask;
bx_ = visual->blue_mask;
#endif
-#if _MACOSX
- // tk visual masks are bogus
- unsigned long red_mask, green_mask, blue_mask, alpha_mask;
- macosxGetMasks(&red_mask, &green_mask, &blue_mask, &alpha_mask);
-
- rx_ = red_mask;
- gx_ = green_mask;
- bx_ = blue_mask;
-#endif
#if _WIN32
// windows masks are plain wrong
rx_ = 0x7C00;
@@ -119,7 +105,7 @@ void TrueColor16::encodeTrueColor(unsigned char* src, XImage* ximage)
{
int& width = ximage->width;
int& height = ximage->height;
- char* data = XImageData(ximage);
+ char* data = ximage->data;
int msb = ximage->byte_order;
const unsigned char* ptr = src;
diff --git a/saotk/widget/truecolor24.C b/saotk/widget/truecolor24.C
index 8f65558..b71655b 100644
--- a/saotk/widget/truecolor24.C
+++ b/saotk/widget/truecolor24.C
@@ -5,35 +5,26 @@
#include "truecolor24.h"
#include "util.h"
-#ifdef _MACOSX
-extern void macosxGetMasks(unsigned long*, unsigned long*,
- unsigned long*, unsigned long*);
-#endif
-
TrueColor24::TrueColor24(Visual* visual)
{
#if !(_WIN32 || _MACOSX)
+ ax_ = 0;
rx_ = visual->red_mask;
gx_ = visual->green_mask;
bx_ = visual->blue_mask;
- ax_ = 0;
#endif
#if _MACOSX
- // tk visual masks are bogus
- unsigned long red_mask, green_mask, blue_mask, alpha_mask;
- macosxGetMasks(&red_mask, &green_mask, &blue_mask, &alpha_mask);
-
- rx_ = red_mask;
- gx_ = green_mask;
- bx_ = blue_mask;
- ax_ = alpha_mask;
+ ax_ = 0xFF000000;
+ rx_ = 0x00FF0000;
+ gx_ = 0x0000FF00;
+ bx_ = 0x000000FF;
#endif
#if _WIN32
// windows masks are plain wrong
+ ax_ = 0;
rx_ = 0x00FF0000;
gx_ = 0x0000FF00;
bx_ = 0x000000FF;
- ax_ = 0;
#endif
rs_ = decodeMask((unsigned long)rx_);
@@ -137,6 +128,10 @@ void TrueColor24::encodeTrueColor32(XColor* src, char* dest, XImage* ximage)
unsigned int g = (unsigned char)src->green;
unsigned int b = (unsigned char)src->blue;
unsigned int v = 0;
+#ifdef _MACOSX
+ unsigned int a = 0xff;
+ v |= a << as_;
+#endif
v |= r << rs_;
v |= g << gs_;
v |= b << bs_;
@@ -190,7 +185,7 @@ void TrueColor24::encodeTrueColor24(unsigned char* src, XImage* ximage)
{
int& width = ximage->width;
int& height = ximage->height;
- char* data = XImageData(ximage);
+ char* data = ximage->data;
int bytesPerPixel = ximage->bits_per_pixel/8;
int msb = ximage->byte_order;
@@ -238,7 +233,7 @@ void TrueColor24::encodeTrueColor32(unsigned char* src, XImage* ximage)
{
int& width = ximage->width;
int& height = ximage->height;
- char* data = XImageData(ximage);
+ char* data = ximage->data;
int bytesPerPixel = ximage->bits_per_pixel/8;
int msb = ximage->byte_order;
diff --git a/saotk/widget/truecolor8.C b/saotk/widget/truecolor8.C
index 38f6821..49401fa 100644
--- a/saotk/widget/truecolor8.C
+++ b/saotk/widget/truecolor8.C
@@ -5,28 +5,14 @@
#include "truecolor8.h"
#include "util.h"
-#ifdef _MACOSX
-extern void macosxGetMasks(unsigned long*, unsigned long*,
- unsigned long*, unsigned long*);
-#endif
-
TrueColor8::TrueColor8(Visual* visual)
{
-#if !(_WIN32 || _MACOSX)
+#if !(_WIN32)
rx_ = visual->red_mask;
gx_ = visual->green_mask;
bx_ = visual->blue_mask;
#endif
-#if _MACOSX
- // tk visual masks are bogus
- unsigned long red_mask, green_mask, blue_mask, alpha_mask;
- macosxGetMasks(&red_mask, &green_mask, &blue_mask, &alpha_mask);
-
- rx_ = red_mask;
- gx_ = green_mask;
- bx_ = blue_mask;
-#endif
#if _WIN32
// windows masks are plain wrong
rx_ = 0xE0;
@@ -69,7 +55,7 @@ void TrueColor8::encodeTrueColor(unsigned char* src, XImage* ximage)
{
int& width = ximage->width;
int& height = ximage->height;
- char* data = XImageData(ximage);
+ char* data = ximage->data;
const unsigned char* ptr = src;
for (int j=0; j<height; j++) {
diff --git a/saotk/widget/widget.h b/saotk/widget/widget.h
index acc8b26..1f99e56 100644
--- a/saotk/widget/widget.h
+++ b/saotk/widget/widget.h
@@ -23,7 +23,6 @@ using namespace std;
class Attribute;
-// in tkCanvasPs.c
extern float psScale;
// General Defines
diff --git a/src/3d.tcl b/src/3d.tcl
index 12b34e6..5f05817 100644
--- a/src/3d.tcl
+++ b/src/3d.tcl
@@ -47,7 +47,6 @@ proc 3DDialog {} {
set mb $ithreed(mb)
Toplevel $w $mb 6 [msgcat::mc {3D}] 3DDestroyDialog
-
$mb add cascade -label [msgcat::mc {File}] -menu $mb.file
$mb add cascade -label [msgcat::mc {Method}] -menu $mb.method
$mb add cascade -label [msgcat::mc {Highlite}] -menu $mb.highlite
diff --git a/src/Makefile b/src/Makefile
index 637ce39..bb6007f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -104,6 +104,8 @@ SCRIPTS = \
mfile.tcl \
mframe.tcl \
mhelp.tcl \
+ macosx.tcl \
+ macosxextra.tcl \
mosaicimage.tcl \
mosaicimageiraf.tcl \
mosaicimagewcs.tcl \
@@ -175,14 +177,10 @@ SCRIPTS = \
vector.tcl \
vo.tcl \
wcs.tcl \
+ win32.tcl \
xmfbox.tcl \
xpa.tcl
-INDEX = pkgIndex.tcl
-
-index : $(SCRIPTS)
- echo "pkg_mkIndex . $(SCRIPTS)" | ../bin/tclsh8.4
-
msgs : FORCE
grep 'msgcat::mc' $(SCRIPTS) | cut -d[ -f2 | sed -e 's/::mc/::mcset AAA /' -e 's/]/ ""/' | sort | uniq > ../msgs/tmpl.tcl
@@ -190,6 +188,5 @@ clean : FORCE
$(RM) core *~ *#
distclean : clean
- $(RM) $(INDEX)
FORCE :
diff --git a/src/analysis.tcl b/src/analysis.tcl
index 0c6c353..b87c40d 100644
--- a/src/analysis.tcl
+++ b/src/analysis.tcl
@@ -1736,7 +1736,7 @@ proc AnalysisEntry {message resultvar} {
proc AnalysisPrefOpen {varname} {
upvar $varname var
- FileLastFull analysisfbox $var
+ FileLast analysisfbox $var
set var [OpenFileDialog analysisfbox]
}
diff --git a/src/backup.tcl b/src/backup.tcl
index 9d919e0..8388b50 100644
--- a/src/backup.tcl
+++ b/src/backup.tcl
@@ -101,15 +101,8 @@ proc Backup {fn} {
# Colorbar
ColorbarBackupCmaps $ch $dir
- switch -- $ds9(visual) {
- pseudocolor {
- ColorbarBackup $ch colorbar
- }
- truecolor {
- ColorbarBackup $ch colorbar
- ColorbarBackup $ch colorbarrgb
- }
- }
+ ColorbarBackup $ch colorbar
+ ColorbarBackup $ch colorbarrgb
# Frames
foreach ff $ds9(frames) {
diff --git a/src/bin.tcl b/src/bin.tcl
index e5e2add..c37ed5b 100644
--- a/src/bin.tcl
+++ b/src/bin.tcl
@@ -204,7 +204,6 @@ proc BinDialog {} {
set mb $ibin(mb)
Toplevel $w $mb 6 [msgcat::mc {Binning Parameters}] BinDestroyDialog
-
$mb add cascade -label [msgcat::mc {File}] -menu $mb.file
$mb add cascade -label [msgcat::mc {Edit}] -menu $mb.edit
$mb add cascade -label [msgcat::mc {Method}] -menu $mb.method
diff --git a/src/buttons.tcl b/src/buttons.tcl
index a40d62d..5a54706 100644
--- a/src/buttons.tcl
+++ b/src/buttons.tcl
@@ -170,11 +170,25 @@ proc RadioButtonCB {button value varname id op} {
upvar #0 $varname var
global $varname
+ global ds9
+
if {[$button cget -state] != {disabled}} {
- if {$var($id) == $value} {
- $button configure -state active
- } else {
- $button configure -state normal
+ switch $ds9(wm) {
+ x11 {
+ if {$var($id) == $value} {
+ $button configure -state active
+ } else {
+ $button configure -state normal
+ }
+ }
+ win32 -
+ aqua {
+ if {$var($id) == $value} {
+ $button configure -default active
+ } else {
+ $button configure -default normal
+ }
+ }
}
}
}
@@ -189,11 +203,25 @@ proc CheckButtonCB {button varname id op} {
upvar #0 $varname var
global $varname
+ global ds9
+
if {[$button cget -state] != {disabled}} {
- if {$var($id)} {
- $button configure -state active
- } else {
- $button configure -state normal
+ switch $ds9(wm) {
+ x11 {
+ if {$var($id)} {
+ $button configure -state active
+ } else {
+ $button configure -state normal
+ }
+ }
+ win32 -
+ aqua {
+ if {$var($id)} {
+ $button configure -default active
+ } else {
+ $button configure -default normal
+ }
+ }
}
}
}
diff --git a/src/catcmd.tcl b/src/catcmd.tcl
index fd5b3f7..052a563 100644
--- a/src/catcmd.tcl
+++ b/src/catcmd.tcl
@@ -55,6 +55,8 @@ proc CATSelectBrowseCmd {varname ss rc} {
upvar #0 $varname var
global $varname
+ puts stderr "CATSelectBrowseCmd $varname ss=$ss rc=$rc"
+
# starts at 1
global debug
if {$debug(tcl,cat)} {
@@ -88,6 +90,17 @@ proc CATSelectBrowseCmd {varname ss rc} {
lappend rowlist $rr
}
set rowlist [lsort -unique $rowlist]
+
+ # kludge
+ # tktable can return bogus numbers if arrow keys are used
+ # try to fix
+ if {$row == 0} {
+ set row 1
+ }
+ if {[llength $rowlist] <= 1} {
+ set rowlist $row
+ }
+
foreach rr $rowlist {
lappend ${varname}(blink,marker) "\{${varname}.${rr}\}"
}
diff --git a/src/catdialog.tcl b/src/catdialog.tcl
index 6e8c2c8..dcfa4f4 100644
--- a/src/catdialog.tcl
+++ b/src/catdialog.tcl
@@ -98,8 +98,8 @@ proc CATDialog {varname format catalog title action} {
} else {
set tt [msgcat::mc {Catalog Tool}]
}
- Toplevel $w $mb 7 $tt "CATDestroy $varname"
+ Toplevel $w $mb 7 $tt "CATDestroy $varname"
$mb add cascade -label [msgcat::mc {File}] -menu $mb.file
$mb add cascade -label [msgcat::mc {Edit}] -menu $mb.edit
CATServerMenu $varname
diff --git a/src/catsym.tcl b/src/catsym.tcl
index 609cc7f..b455f20 100644
--- a/src/catsym.tcl
+++ b/src/catsym.tcl
@@ -72,9 +72,9 @@ proc CATSymDialog {parent} {
set mb $var(mb)
Toplevel $w $mb 7 [msgcat::mc {Symbol Editor}] "CATSymDestroy $varname"
+ $mb add cascade -label [msgcat::mc {File}] -menu $mb.file
# menu
- $mb add cascade -label [msgcat::mc {File}] -menu $mb.file
menu $mb.file
$mb.file add command -label [msgcat::mc {Apply}] \
-command "CATSymApply $varname"
diff --git a/src/centroid.tcl b/src/centroid.tcl
index 7451201..5fb9276 100644
--- a/src/centroid.tcl
+++ b/src/centroid.tcl
@@ -29,7 +29,6 @@ proc CentroidDialog {} {
set mb $icentroid(mb)
Toplevel $w $mb 6 [msgcat::mc {Centroid Parameters}] CentroidDestroyDialog
-
$mb add cascade -label [msgcat::mc {File}] -menu $mb.file
$mb add cascade -label [msgcat::mc {Edit}] -menu $mb.edit
diff --git a/src/colorbar.tcl b/src/colorbar.tcl
index e48f249..84cfbe7 100644
--- a/src/colorbar.tcl
+++ b/src/colorbar.tcl
@@ -49,69 +49,42 @@ proc CreateColorbar {} {
global canvas
global view
- switch -- $ds9(visual) {
- pseudocolor {
- $ds9(canvas) create colorbar$ds9(visual)$ds9(depth) \
- -private $icolorbar(private) \
- -tag colorbar \
- -anchor nw \
- -helvetica $ds9(helvetica) \
- -courier $ds9(courier) \
- -times $ds9(times)
-
- # And set the two windows that where created before the
- # colorbar was created, to the new colormap
-
- colorbar colormap window "$ds9(main)"
-
- $ds9(canvas) bind colorbar <Motion> [list MotionColorbar %x %y]
- $ds9(canvas) bind colorbar <Enter> [list EnterColorbar %x %y]
- $ds9(canvas) bind colorbar <Leave> [list LeaveColorbar]
-
- $ds9(canvas) bind colorbar <Button-1> [list Button1Colorbar %x %y]
- $ds9(canvas) bind colorbar <B1-Motion> [list Motion1Colorbar %x %y]
- $ds9(canvas) bind colorbar <ButtonRelease-1> [list Release1Colorbar %x %y]
- $ds9(canvas) bind colorbar <Key> [list KeyColorbar %K %A %x %y]
- $ds9(canvas) bind colorbar <KeyRelease> [list KeyReleaseColorbar %K %A %x %y]
- }
- truecolor {
- $ds9(canvas) create colorbar$ds9(visual)$ds9(depth) \
- -colors 2048 \
- -tag colorbar \
- -anchor nw \
- -helvetica $ds9(helvetica) \
- -courier $ds9(courier) \
- -times $ds9(times)
-
- $ds9(canvas) bind colorbar <Motion> [list MotionColorbar %x %y]
- $ds9(canvas) bind colorbar <Enter> [list EnterColorbar %x %y]
- $ds9(canvas) bind colorbar <Leave> [list LeaveColorbar]
-
- $ds9(canvas) bind colorbar <Button-1> [list Button1Colorbar %x %y]
- $ds9(canvas) bind colorbar <B1-Motion> [list Motion1Colorbar %x %y]
- $ds9(canvas) bind colorbar <ButtonRelease-1> \
- [list Release1Colorbar %x %y]
- $ds9(canvas) bind colorbar <Double-1> [list Double1Colorbar %x %y]
- $ds9(canvas) bind colorbar <Double-ButtonRelease-1> \
- [list DoubleRelease1Colorbar %x %y]
-
- $ds9(canvas) bind colorbar <Key> [list KeyColorbar %K %A %x %y]
- $ds9(canvas) bind colorbar <KeyRelease> \
- [list KeyReleaseColorbar %K %A %x %y]
-
- $ds9(canvas) create colorbarrgb$ds9(visual)$ds9(depth) \
- -colors 2048 \
- -tag colorbarrgb \
- -anchor nw \
- -helvetica $ds9(helvetica) \
- -courier $ds9(courier) \
- -times $ds9(times)
-
- $ds9(canvas) bind colorbarrgb <Motion> [list MotionColorbar %x %y]
- $ds9(canvas) bind colorbarrgb <Enter> [list EnterColorbar %x %y]
- $ds9(canvas) bind colorbarrgb <Leave> [list LeaveColorbar]
- }
- }
+ $ds9(canvas) create colorbar$ds9(visual)$ds9(depth) \
+ -colors 2048 \
+ -tag colorbar \
+ -anchor nw \
+ -helvetica $ds9(helvetica) \
+ -courier $ds9(courier) \
+ -times $ds9(times)
+
+ $ds9(canvas) bind colorbar <Motion> [list MotionColorbar %x %y]
+ $ds9(canvas) bind colorbar <Enter> [list EnterColorbar %x %y]
+ $ds9(canvas) bind colorbar <Leave> [list LeaveColorbar]
+
+ $ds9(canvas) bind colorbar <Button-1> [list Button1Colorbar %x %y]
+ $ds9(canvas) bind colorbar <B1-Motion> [list Motion1Colorbar %x %y]
+ $ds9(canvas) bind colorbar <ButtonRelease-1> \
+ [list Release1Colorbar %x %y]
+ $ds9(canvas) bind colorbar <Double-1> [list Double1Colorbar %x %y]
+ $ds9(canvas) bind colorbar <Double-ButtonRelease-1> \
+ [list DoubleRelease1Colorbar %x %y]
+
+ $ds9(canvas) bind colorbar <Key> [list KeyColorbar %K %A %x %y]
+ $ds9(canvas) bind colorbar <KeyRelease> \
+ [list KeyReleaseColorbar %K %A %x %y]
+
+ $ds9(canvas) create colorbarrgb$ds9(visual)$ds9(depth) \
+ -colors 2048 \
+ -tag colorbarrgb \
+ -anchor nw \
+ -helvetica $ds9(helvetica) \
+ -courier $ds9(courier) \
+ -times $ds9(times)
+
+ $ds9(canvas) bind colorbarrgb <Motion> [list MotionColorbar %x %y]
+ $ds9(canvas) bind colorbarrgb <Enter> [list EnterColorbar %x %y]
+ $ds9(canvas) bind colorbarrgb <Leave> [list LeaveColorbar]
+
LayoutColorbar
}
@@ -988,6 +961,7 @@ proc UpdateColorDialog {} {
if {[winfo exists $icolorbar(top)]} {
set dcolorbar(contrast) [$current(colorbar) get contrast]
set dcolorbar(bias) [$current(colorbar) get bias]
+ set end [expr $icolorbar(contrib)+$icolorbar(start)]
if {$current(frame) != {}} {
switch -- [$current(frame) get type] {
@@ -997,7 +971,7 @@ proc UpdateColorDialog {} {
"[msgcat::mc {Load Colormap}]..." -state normal
$icolorbar(mb).file entryconfig \
"[msgcat::mc {Save Colormap}]..." -state normal
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end} {incr ii} {
$icolorbar(mb).colormap entryconfig $ii -state normal
}
$icolorbar(mb).colormap entryconfig \
@@ -1010,7 +984,7 @@ proc UpdateColorDialog {} {
"[msgcat::mc {Load Colormap}]..." -state disabled
$icolorbar(mb).file entryconfig \
"[msgcat::mc {Save Colormap}]..." -state disabled
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end} {incr ii} {
$icolorbar(mb).colormap entryconfig $ii -state disabled
}
$icolorbar(mb).colormap entryconfig \
@@ -1024,7 +998,7 @@ proc UpdateColorDialog {} {
"[msgcat::mc {Load Colormap}]..." -state normal
$icolorbar(mb).file entryconfig \
"[msgcat::mc {Save Colormap}]..." -state normal
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end(contrib)} {incr ii} {
$icolorbar(mb).colormap entryconfig $ii -state normal
}
$icolorbar(mb).colormap entryconfig [msgcat::mc {Contributed}] \
@@ -1052,17 +1026,15 @@ proc LayoutColorbar {} {
-fontweight $colorbar(font,weight) \
-fontslant $colorbar(font,slant) \
- if {$ds9(visual) == {truecolor}} {
- colorbarrgb configure \
- -size $colorbar(size) \
- -ticks $colorbar(ticks) \
- -numerics $colorbar(numerics) \
- -space $colorbar(space) \
- -font $colorbar(font) \
- -fontsize $colorbar(font,size) \
- -fontweight $colorbar(font,weight) \
- -fontslant $colorbar(font,slant) \
- }
+ colorbarrgb configure \
+ -size $colorbar(size) \
+ -ticks $colorbar(ticks) \
+ -numerics $colorbar(numerics) \
+ -space $colorbar(space) \
+ -font $colorbar(font) \
+ -fontsize $colorbar(font,size) \
+ -fontweight $colorbar(font,weight) \
+ -fontslant $colorbar(font,slant) \
switch -- $colorbar(orientation) {
horizontal {
@@ -1074,12 +1046,10 @@ proc LayoutColorbar {} {
-height $icolorbar(horizontal,height) \
-orientation 0
- if {$ds9(visual) == {truecolor}} {
- colorbarrgb configure -x $xx -y $yy \
- -width $canvas(width) \
- -height $icolorbar(horizontal,height) \
- -orientation 0
- }
+ colorbarrgb configure -x $xx -y $yy \
+ -width $canvas(width) \
+ -height $icolorbar(horizontal,height) \
+ -orientation 0
}
vertical {
set xx [expr $canvas(width) + $canvas(gap)]
@@ -1090,12 +1060,10 @@ proc LayoutColorbar {} {
-height $canvas(height) \
-orientation 1
- if {$ds9(visual) == {truecolor}} {
- colorbarrgb configure -x $xx -y $yy \
- -width $icolorbar(vertical,width) \
- -height $canvas(height) \
- -orientation 1
- }
+ colorbarrgb configure -x $xx -y $yy \
+ -width $icolorbar(vertical,width) \
+ -height $canvas(height) \
+ -orientation 1
}
}
}
diff --git a/src/command.tcl b/src/command.tcl
index 9d07cbb..6108776 100644
--- a/src/command.tcl
+++ b/src/command.tcl
@@ -7,7 +7,7 @@ package provide DS9 1.0
proc BadVisualError {} {
global ds9
- Error [msgcat::mc {Sorry, DS9 requires a Pseudocolor8, Truecolor8, Truecolor16, Truecolor24 visual be available}]
+ Error [msgcat::mc {Sorry, DS9 requires a Truecolor8, Truecolor16, Truecolor24 visual be available}]
exit
}
diff --git a/src/ds9.tcl b/src/ds9.tcl
index 456ea9f..531345a 100755
--- a/src/ds9.tcl
+++ b/src/ds9.tcl
@@ -7,7 +7,7 @@ proc DS9Def {} {
global pds9
set ds9(title) "$ds9(app)"
- set ds9(version) {7.3 beta 2}
+ set ds9(version) {7.3 beta 3}
set ds9(top) .
set ds9(mb) .mb
@@ -51,7 +51,6 @@ proc DS9Def {} {
set ds9(event,opendoc) {}
set ds9(event,printdoc) {}
- set ds9(dialog,dir) {}
set ds9(tmpdir) {}
switch $ds9(wm) {
@@ -159,75 +158,122 @@ proc DS9Def {} {
set pds9(threads) 8
}
-# who are we?
-set ds9(app) [file rootname [file tail $argv0]]
+proc DEBUGS {str} {
+ set ch [open "/Users/joye/debug.txt" "a+"]
+ puts $ch $str
+ close $ch
+}
+
# if we have a problem at this point, dump simple message and exit
if {[catch {tk windowingsystem} ds9(wm)]} {
puts stderr "Unable to initialize window system."
exit
}
-# Styles
+# who are we?
+set ds9(app) [file tail [info nameofexecutable]]
set ds9(app,bg) [ttk::style lookup "." -background]
switch $ds9(wm) {
x11 {
- # change just default style
- ttk::style theme settings default \
- [list ;
- ttk::style configure TLabel -borderwidth 2 -padding 1;
- ttk::style configure TEntry -fieldbackground $ds9(app,bg) -padding 1;
- ]
- }
- win32 {}
- aqua {}
-}
+ # set to absolute path so that if -cd command is used,
+ # so we can still find our files
+ set ds9(root) [file normalize [file join [pwd] zvfsmntpt]]
-# set to absolute path so that if -cd command is used,
-# so we can still find our files
-set ds9(root) "[pwd]/zvfsmntpt"
-#set ds9(root) "/tmp/zvfsmntpt"
+ if {![namespace exists msgcat]} {
+ source $ds9(root)/tcl8/8.5/msgcat-1.5.0.tm
+ }
+ if {![namespace exists http]} {
+ source $ds9(root)/tcl8/8.6/http-2.8.5.tm
+ }
-# tcl modules
-if {![namespace exists msgcat]} {
- source $ds9(root)/tcl8/8.5/msgcat-1.5.0.tm
-}
-if {![namespace exists http]} {
- source $ds9(root)/tcl8/8.6/http-2.8.5.tm
-}
+ source $ds9(root)/tk8.6/tearoff.tcl
+ source $ds9(root)/tk8.6/comdlg.tcl
+ source $ds9(root)/tk8.6/focus.tcl
+ source $ds9(root)/tk8.6/mkpsenc.tcl
+ source $ds9(root)/tk8.6/msgbox.tcl
+ source $ds9(root)/tk8.6/optMenu.tcl
+ source $ds9(root)/tk8.6/unsupported.tcl
+
+ source $ds9(root)/tcllib1.15/base64/base64.tcl
+ source $ds9(root)/tcllib1.15/log/log.tcl
+ source $ds9(root)/tcllib1.15/ftp/ftp.tcl
+ source $ds9(root)/tcllib1.15/textutil/repeat.tcl
+ source $ds9(root)/tcllib1.15/textutil/tabify.tcl
+ source $ds9(root)/tcllib1.15/math/fuzzy.tcl
+
+ source $ds9(root)/tkcon2.5/tkcon.tcl
+ source $ds9(root)/xmlrpc0.3/xmlrpc.tcl
+ source $ds9(root)/tlt3.0/graph.tcl
+
+ source $ds9(root)/src/source.tcl
+
+ set tlt_library $ds9(root)/tlt3.0
-source $ds9(root)/tk8.6/tearoff.tcl
-source $ds9(root)/tk8.6/comdlg.tcl
-source $ds9(root)/tk8.6/focus.tcl
-source $ds9(root)/tk8.6/mkpsenc.tcl
-source $ds9(root)/tk8.6/msgbox.tcl
-source $ds9(root)/tk8.6/optMenu.tcl
-source $ds9(root)/tk8.6/unsupported.tcl
+ # fix ::tk and msgcat
+ rename ::tk::msgcat::mc {}
+ rename ::tk::msgcat::mcmax {}
-source $ds9(root)/tcllib1.15/base64/base64.tcl
-source $ds9(root)/tcllib1.15/log/log.tcl
-source $ds9(root)/tcllib1.15/ftp/ftp.tcl
-source $ds9(root)/tcllib1.15/textutil/repeat.tcl
-source $ds9(root)/tcllib1.15/textutil/tabify.tcl
-source $ds9(root)/tcllib1.15/math/fuzzy.tcl
+ namespace import ::msgcat::mc
+ namespace import ::msgcat::mcmax
+ ::msgcat::mcload [file join $::tk_library msgs]
-source $ds9(root)/tkcon2.5/tkcon.tcl
-source $ds9(root)/xmlrpc0.3/xmlrpc.tcl
-source $ds9(root)/blt3.0/graph.tcl
+ # fix ::tk::dialog::file
+ set ::tk::dialog::file::showHiddenVar 0
+ set ::tk::dialog::file::showHiddenBtn 1
-source $ds9(root)/src/source.tcl
+ # change just default style
+ ttk::style theme settings default [list ; ttk::style configure TLabel -borderwidth 2 -padding 1; ttk::style configure TEntry -fieldbackground $ds9(app,bg) -padding 1;]
+ }
+ aqua {
+ set res [file normalize [file dirname [file dirname $argv0]]]
+ lappend auto_path $res
+ # tlt uses tclIndex
+ lappend auto_path [file normalize [file join $res tlt3.0]]
+ set ds9(root) [file normalize [file join [file dirname $argv0] ".."]]
+
+ set tlt_library [file normalize [file join $res tlt3.0]]
+
+ package require http
+ package require msgcat
+ package require DS9
+ package require base64
+ package require log
+ package require ftp
+ package require textutil
+ package require math
+ package require tkcon
+ package require xmlrpc
+
+ proc ::tk::mac::OpenDocument {args} {
+ global ds9
+
+ set ds9(event,opendoc) $args
+ if {!$ds9(init)} {
+ MacOSXOpenDocEvent 1
+ }
+ }
+
+ proc ::tk::mac::PrintDocument {args} {
+ global ds9
-# fix ::tk and msgcat
-rename ::tk::msgcat::mc {}
-rename ::tk::msgcat::mcmax {}
+ set ds9(event,printdoc) $args
+ if {!$ds9(init)} {
+ MacOSXPrintDocEvent 0
+ }
+ }
-namespace import ::msgcat::mc
-namespace import ::msgcat::mcmax
-::msgcat::mcload [file join $::tk_library msgs]
+ proc ::tk::mac::ShowPreferences {} {
+ PrefsDialog
+ }
-# fix ::tk::dialog::file
-set ::tk::dialog::file::showHiddenVar 0
-set ::tk::dialog::file::showHiddenBtn 1
+ proc ::tk::mac::Quit {args} {
+ QuitDS9
+ }
+ }
+ win32 {
+ }
+}
# Define Variables
DS9Def
@@ -302,9 +348,6 @@ switch $tcl_platform(platform) {
windows {}
}
-# set the appname
-tk appname $ds9(app)
-
# environment vars
# we don't want to see any error messages if xpa is not available
if { [info exists env(XPA_VERBOSITY)] == 0 } {
@@ -368,7 +411,6 @@ wm withdraw $ds9(top)
wm title $ds9(top) "SAOImage $ds9(title)"
wm iconname $ds9(top) "SAOImage $ds9(title)"
wm protocol $ds9(top) WM_DELETE_WINDOW QuitDS9
-$ds9(top) configure -menu $ds9(mb)
# Theme
PrefsTheme
@@ -430,7 +472,6 @@ switch $ds9(wm) {
}
switch -- $ds9(visual)$ds9(depth) {
- pseudocolor8 {}
truecolor8 {}
truecolor16 {}
truecolor24 {}
@@ -539,4 +580,3 @@ after $ds9(msg,timeout) [list ErrorTimer]
# ok, we're done
set ds9(init) 0
-
diff --git a/src/frame.tcl b/src/frame.tcl
index 322a75e..6d5637d 100644
--- a/src/frame.tcl
+++ b/src/frame.tcl
@@ -86,38 +86,21 @@ proc CreateNameNumberFrame {which type} {
set active($ds9(next)) 1
# and create the frame
- switch -- $ds9(visual) {
- pseudocolor {
- switch -- $type {
- base {
- $ds9(canvas) create frame$ds9(visual)$ds9(depth) \
- -command $ds9(next)
- $ds9(next) colormap [colorbar get colormap]
- }
- rgb -
- 3d {
- Error [msgcat::mc {Unable to create RGB or 3D frame with pseudocolor visual}]
- }
- }
+ switch -- $type {
+ base {
+ $ds9(canvas) create frame$ds9(visual)$ds9(depth) \
+ -command $ds9(next)
+ $ds9(next) colormap [colorbar get colormap]
}
- truecolor {
- switch -- $type {
- base {
- $ds9(canvas) create frame$ds9(visual)$ds9(depth) \
- -command $ds9(next)
- $ds9(next) colormap [colorbar get colormap]
- }
- rgb {
- $ds9(canvas) create framergb$ds9(visual)$ds9(depth) \
- -command $ds9(next)
- $ds9(next) colormap [colorbarrgb get colormap]
- }
- 3d {
- $ds9(canvas) create frame3d$ds9(visual)$ds9(depth) \
- -command $ds9(next)
- $ds9(next) colormap [colorbar get colormap]
- }
- }
+ rgb {
+ $ds9(canvas) create framergb$ds9(visual)$ds9(depth) \
+ -command $ds9(next)
+ $ds9(next) colormap [colorbarrgb get colormap]
+ }
+ 3d {
+ $ds9(canvas) create frame3d$ds9(visual)$ds9(depth) \
+ -command $ds9(next)
+ $ds9(next) colormap [colorbar get colormap]
}
}
@@ -550,7 +533,7 @@ proc EnterFrame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "EnterFrame"
+ puts stderr "EnterFrame $which"
}
# check to see if this event was generated while processing other events
@@ -603,7 +586,7 @@ proc LeaveFrame {which} {
global debug
if {$debug(tcl,events)} {
- puts stderr "LeaveFrame"
+ puts stderr "LeaveFrame $which"
}
# check to see if this event was generated while processing other events
@@ -639,7 +622,7 @@ proc LeaveFrame {which} {
proc MotionFrame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "MotionFrame"
+ puts stderr "MotionFrame $which"
}
DoMotion $which $x $y sizing fleur
@@ -648,7 +631,7 @@ proc MotionFrame {which x y} {
proc ShiftMotionFrame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ShiftMotionFrame"
+ puts stderr "ShiftMotionFrame $which"
}
DoMotion $which $x $y exchange fleur
@@ -657,7 +640,7 @@ proc ShiftMotionFrame {which x y} {
proc ControlMotionFrame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ControlMotionFrame"
+ puts stderr "ControlMotionFrame $which"
}
DoMotion $which $x $y sizing draped_box
@@ -711,7 +694,7 @@ proc Button1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Button1Frame"
+ puts stderr "Button1Frame $which"
}
# let others know that the mouse is down
@@ -812,7 +795,7 @@ proc ShiftButton1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ShiftButton1Frame"
+ puts stderr "ShiftButton1Frame $which"
}
# let others know that the mouse is down
@@ -853,7 +836,7 @@ proc ControlButton1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ControlButton1Frame"
+ puts stderr "ControlButton1Frame $which"
}
# let others know that the mouse is down
@@ -895,7 +878,7 @@ proc ControlShiftButton1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ControlShiftButton1Frame"
+ puts stderr "ControlShiftButton1Frame $which"
}
# let others know that the mouse is down
@@ -933,7 +916,7 @@ proc Motion1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Motion1Frame"
+ puts stderr "Motion1Frame $which"
}
# abort if we are here by accident (such as a double click)
@@ -1014,7 +997,7 @@ proc Release1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Release1Frame"
+ puts stderr "Release1Frame $which"
}
# abort if we are here by accident (such as a double click)
@@ -1091,7 +1074,7 @@ proc Double1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Double1Frame"
+ puts stderr "Double1Frame $which"
}
switch -- $current(mode) {
@@ -1119,7 +1102,7 @@ proc DoubleRelease1Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "DoubleRelease1Frame"
+ puts stderr "DoubleRelease1Frame $which"
}
switch -- $current(mode) {
@@ -1157,7 +1140,7 @@ proc ShiftButton2Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "ShiftButton2Frame"
+ puts stderr "ShiftButton2Frame $which"
}
set ds9(sb2) 1
@@ -1166,7 +1149,7 @@ proc ShiftButton2Frame {which x y} {
proc Motion2Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Motion2Frame"
+ puts stderr "Motion2Frame $which"
}
MotionPan $which $x $y
@@ -1177,7 +1160,7 @@ proc Release2Frame {which x y} {
global debug
if {$debug(tcl,events)} {
- puts stderr "Release2Frame"
+ puts stderr "Release2Frame $which"
}
ReleasePan $which $x $y
@@ -1806,52 +1789,36 @@ proc FrameToFront {} {
set which $current(frame)
# process proper colorbar
- switch -- $ds9(visual) {
- pseudocolor {
+ switch -- [$which get type] {
+ base -
+ 3d {
if {$view(colorbar)} {
colorbar show
} else {
colorbar hide
}
+ colorbarrgb hide
set current(colorbar) colorbar
colorbar colorbar [$which get colorbar]
colorbar tag "\{[$which get colorbar tag]\}"
set colorbar(map) [colorbar get name]
- }
- truecolor {
- switch -- [$which get type] {
- base -
- 3d {
- if {$view(colorbar)} {
- colorbar show
- } else {
- colorbar hide
- }
- colorbarrgb hide
- set current(colorbar) colorbar
- colorbar colorbar [$which get colorbar]
- colorbar tag "\{[$which get colorbar tag]\}"
- set colorbar(map) [colorbar get name]
-
- $ds9(canvas) raise colorbar colorbarrgb
- }
- rgb {
- colorbar hide
- if {$view(colorbar)} {
- colorbarrgb show
- } else {
- colorbarrgb hide
- }
- set current(colorbar) colorbarrgb
+ $ds9(canvas) raise colorbar colorbarrgb
+ }
+ rgb {
+ colorbar hide
+ if {$view(colorbar)} {
+ colorbarrgb show
+ } else {
+ colorbarrgb hide
+ }
+ set current(colorbar) colorbarrgb
- colorbarrgb colorbar [$which get colorbar]
- colorbarrgb rgb channel [$which get rgb channel]
+ colorbarrgb colorbar [$which get colorbar]
+ colorbarrgb rgb channel [$which get rgb channel]
- $ds9(canvas) raise colorbarrgb colorbar
- }
- }
+ $ds9(canvas) raise colorbarrgb colorbar
}
}
set colorbar(invert) [$current(colorbar) get invert]
diff --git a/src/group.tcl b/src/group.tcl
index 97f3431..5598beb 100644
--- a/src/group.tcl
+++ b/src/group.tcl
@@ -78,7 +78,7 @@ proc GroupDialog {} {
set dgroup(list) [listbox $f.box \
-yscroll [list $f.scroll set] \
-setgrid true \
- -selectmode single \
+ -selectmode multiple \
]
grid $f.box $f.scroll -sticky news
grid rowconfigure $f 0 -weight 1
@@ -108,9 +108,11 @@ proc GroupButtonDialog {} {
if {$current(frame) != {}} {
$current(frame) marker unselect all
- set i [$dgroup(list) curselection]
- if {[string length $i] != 0} {
- $current(frame) marker "\{[$dgroup(list) get $i]\}" select
+ set rr [$dgroup(list) curselection]
+ foreach ii $rr {
+ if {[string length $ii] != 0} {
+ $current(frame) marker "\{[$dgroup(list) get $ii]\}" select
+ }
}
}
}
diff --git a/src/hvsup.tcl b/src/hvsup.tcl
index 7d57665..686a155 100644
--- a/src/hvsup.tcl
+++ b/src/hvsup.tcl
@@ -1149,6 +1149,9 @@ proc HVParseHTML {varname} {
if {[string length $r(query)] != 0} {
append base "?$r(query)"
}
+ # spaces?
+ regsub { } $base {\ } base
+
$var(widget) config -base $base
if {$debug(tcl,hv)} {
diff --git a/src/layout.tcl b/src/layout.tcl
index 0b64f7b..a77f236 100644
--- a/src/layout.tcl
+++ b/src/layout.tcl
@@ -620,23 +620,13 @@ proc LayoutFrames {} {
}
# process proper colorbar
- switch -- $ds9(visual) {
- pseudocolor {
- colorbar show
- set current(colorbar) colorbar
- set colorbar(map) [colorbar get name]
- set colorbar(invert) [colorbar get invert]
- }
- truecolor {
- colorbar show
- colorbarrgb hide
- $ds9(canvas) raise colorbar colorbarrgb
-
- set current(colorbar) colorbar
- set colorbar(map) [colorbar get name]
- set colorbar(invert) [colorbar get invert]
- }
- }
+ colorbar show
+ colorbarrgb hide
+ $ds9(canvas) raise colorbar colorbarrgb
+
+ set current(colorbar) colorbar
+ set colorbar(map) [colorbar get name]
+ set colorbar(invert) [colorbar get invert]
# update menus/dialogs
UpdateDS9
diff --git a/src/macosx.tcl b/src/macosx.tcl
index 6318702..362fa0e 100644
--- a/src/macosx.tcl
+++ b/src/macosx.tcl
@@ -4,35 +4,6 @@
package provide DS9 1.0
-# ::tk::mac::OpenApplication
-# ::tk::mac::ReopenApplication
-
-proc ::tk::mac::OpenDocument {args} {
- global ds9
-
- set ds9(event,opendoc) $args
- if {!$ds9(init)} {
- MacOSXOpenDocEvent 1
- }
-}
-
-proc ::tk::mac::PrintDocument {args} {
- global ds9
-
- set ds9(event,printdoc) $args
- if {!$ds9(init)} {
- MacOSXPrintDocEvent 0
- }
-}
-
-proc ::tk::mac::ShowPreferences {} {
- PrefsDialog
-}
-
-proc ::tk::mac::Quit {args} {
- QuitDS9
-}
-
proc MacOSXOpenDocEvent {fc} {
global ds9
@@ -41,7 +12,7 @@ proc MacOSXOpenDocEvent {fc} {
foreach f $ds9(event,opendoc) {
MultiLoad
LoadFitsFile $f {} {}
- FileLastFull fitsfbox $f
+ FileLast fitsfbox $f
}
FinishLoad
@@ -60,7 +31,7 @@ proc MacOSXPrintDocEvent {bye} {
MultiLoad
LoadFitsFile $f {} {}
- FileLastFull fitsfbox $f
+ FileLast fitsfbox $f
FinishLoad
MacOSXPrintPre
diff --git a/src/marker.tcl b/src/marker.tcl
index b0aeb07..7dbd375 100644
--- a/src/marker.tcl
+++ b/src/marker.tcl
@@ -1150,6 +1150,7 @@ proc MarkerLoadFile {filename which format sys sky} {
}
}
+ FileLast markerfbox $filename
UpdateGroupDialog
}
diff --git a/src/mask.tcl b/src/mask.tcl
index a55dfec..9b04720 100644
--- a/src/mask.tcl
+++ b/src/mask.tcl
@@ -152,16 +152,8 @@ proc UpdateMaskMenu {} {
switch -- [$current(frame) get type] {
base {
- switch -- $ds9(visual) {
- pseudocolor {
- $ds9(mb).analysis entryconfig \
- "[msgcat::mc {Mask Parameters}]..." -state disabled
- }
- truecolor {
- $ds9(mb).analysis entryconfig \
- "[msgcat::mc {Mask Parameters}]..." -state normal
- }
- }
+ $ds9(mb).analysis entryconfig \
+ "[msgcat::mc {Mask Parameters}]..." -state normal
}
3d -
rgb {
diff --git a/src/mcolor.tcl b/src/mcolor.tcl
index 87daa36..d75d2a8 100644
--- a/src/mcolor.tcl
+++ b/src/mcolor.tcl
@@ -392,13 +392,14 @@ proc UpdateColorMenu {} {
puts stderr "UpdateColorMenu"
}
+ set end [expr $icolorbar(contrib)+$icolorbar(start)]
if {$current(frame) != {}} {
switch [$current(frame) get type] {
base -
3d {
# menus
# base
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end} {incr ii} {
$ds9(mb).color entryconfig $ii -state normal
}
$ds9(mb).color entryconfig [msgcat::mc {Contributed}] \
@@ -418,7 +419,7 @@ proc UpdateColorMenu {} {
rgb {
# menus
# base
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end} {incr ii} {
$ds9(mb).color entryconfig $ii -state disabled
}
$ds9(mb).color entryconfig [msgcat::mc {Contributed}] \
@@ -439,7 +440,7 @@ proc UpdateColorMenu {} {
} else {
# menus
# base
- for {set ii $icolorbar(start)} {$ii<=$icolorbar(contrib)} {incr ii} {
+ for {set ii $icolorbar(start)} {$ii<$end} {incr ii} {
$ds9(mb).color entryconfig $ii -state normal
}
$ds9(mb).color entryconfig [msgcat::mc {Contributed}] -state normal
diff --git a/src/menu.tcl b/src/menu.tcl
index 3b8b196..1d33ac2 100644
--- a/src/menu.tcl
+++ b/src/menu.tcl
@@ -7,7 +7,11 @@ package provide DS9 1.0
proc CreateMenuBar {} {
global ds9
+ # we need this first, before the configure command
menu $ds9(mb)
+ AppleMenu $ds9(mb)
+ $ds9(top) configure -menu $ds9(mb)
+
$ds9(mb) add cascade -label [msgcat::mc {File}] -menu $ds9(mb).file
$ds9(mb) add cascade -label [msgcat::mc {Edit}] -menu $ds9(mb).edit
$ds9(mb) add cascade -label [msgcat::mc {View}] -menu $ds9(mb).view
@@ -20,7 +24,6 @@ proc CreateMenuBar {} {
$ds9(mb) add cascade -label [msgcat::mc {WCS}] -menu $ds9(mb).wcs
$ds9(mb) add cascade -label [msgcat::mc {Analysis}] -menu $ds9(mb).analysis
- AppleMainMenu $ds9(mb)
FileMainMenu
EditMainMenu
ViewMainMenu
@@ -32,15 +35,10 @@ proc CreateMenuBar {} {
RegionMainMenu
WCSMainMenu
AnalysisMainMenu
-
- switch $ds9(wm) {
- x11 -
- win32 {HelpMenu $ds9(mb)}
- aqua {}
- }
+ HelpMainMenu
}
-proc AppleMainMenu {mb} {
+proc AppleMenu {mb} {
global ds9
switch $ds9(wm) {
@@ -48,14 +46,11 @@ proc AppleMainMenu {mb} {
win32 {}
aqua {
# apple menu
- $mb add cascade -menu $mb.apple
menu $mb.apple
+ $mb add cascade -menu $mb.apple
$mb.apple add command \
-label [msgcat::mc {About SAOImage DS9}] \
-command AboutBox
-
- # help menu
- HelpMenu $mb
}
}
}
diff --git a/src/mframe.tcl b/src/mframe.tcl
index d7b6d77..3218848 100644
--- a/src/mframe.tcl
+++ b/src/mframe.tcl
@@ -928,18 +928,8 @@ proc UpdateFrameMenuStatic {} {
puts stderr "UpdateFrameMenuStatic"
}
- switch -- $ds9(visual) {
- pseudocolor {
- $ds9(mb).frame entryconfig [msgcat::mc {New Frame RGB}] \
- -state disabled
- $ds9(buttons).frame.newrgb configure -state disabled
- }
- truecolor {
- $ds9(mb).frame entryconfig [msgcat::mc {New Frame RGB}] \
- -state normal
- $ds9(buttons).frame.newrgb configure -state normal
- }
- }
+ $ds9(mb).frame entryconfig [msgcat::mc {New Frame RGB}] -state normal
+ $ds9(buttons).frame.newrgb configure -state normal
if {$ds9(active,num) > 0} {
$ds9(mb).frame entryconfig [msgcat::mc {Delete Frame}] -state normal
diff --git a/src/mhelp.tcl b/src/mhelp.tcl
index 7d9f5fc..dbd0439 100644
--- a/src/mhelp.tcl
+++ b/src/mhelp.tcl
@@ -6,38 +6,48 @@ package provide DS9 1.0
# Menu
-proc HelpMenu {mb} {
+proc HelpMainMenu {} {
global ds9
- $mb add cascade -label [msgcat::mc {Help}] -menu $mb.help
+ switch $ds9(wm) {
+ x11 -
+ win32 {}
+ aqua {
+ # window menu
+ menu $ds9(mb).window
+ $ds9(mb) add cascade -label [msgcat::mc {Window}] \
+ -menu $ds9(mb).window
+ }
+ }
- menu $mb.help
- $mb.help add command -label [msgcat::mc {Reference Manual}]\
+ $ds9(mb) add cascade -label [msgcat::mc {Help}] -menu $ds9(mb).help
+ menu $ds9(mb).help
+ $ds9(mb).help add command -label [msgcat::mc {Reference Manual}]\
-command HelpRef
- $mb.help add command -label [msgcat::mc {User Manual}]\
+ $ds9(mb).help add command -label [msgcat::mc {User Manual}]\
-command HelpUser
- $mb.help add command -label [msgcat::mc {Mouse & Keyboard}] \
+ $ds9(mb).help add command -label [msgcat::mc {Mouse & Keyboard}] \
-command HelpKeyboard
- $mb.help add separator
- $mb.help add command -label [msgcat::mc {FAQ}] \
+ $ds9(mb).help add separator
+ $ds9(mb).help add command -label [msgcat::mc {FAQ}] \
-command HelpFAQ
- $mb.help add command -label [msgcat::mc {New Features}] \
+ $ds9(mb).help add command -label [msgcat::mc {New Features}] \
-command HelpNew
- $mb.help add command -label [msgcat::mc {Release Notes}] \
+ $ds9(mb).help add command -label [msgcat::mc {Release Notes}] \
-command HelpRelease
- $mb.help add command -label [msgcat::mc {Help Desk}] \
+ $ds9(mb).help add command -label [msgcat::mc {Help Desk}] \
-command HelpDesk
- $mb.help add separator
- $mb.help add command -label [msgcat::mc {Story of SAOImage DS9}] \
+ $ds9(mb).help add separator
+ $ds9(mb).help add command -label [msgcat::mc {Story of SAOImage DS9}] \
-command HelpStory
- $mb.help add command -label [msgcat::mc {Acknowledgment}] \
+ $ds9(mb).help add command -label [msgcat::mc {Acknowledgment}] \
-command HelpAck
switch $ds9(wm) {
x11 -
win32 {
- $mb.help add separator
- $mb.help add command \
+ $ds9(mb).help add separator
+ $ds9(mb).help add command \
-label "[msgcat::mc {About SAOImage DS9}]..." \
-command AboutBox
}
diff --git a/src/print.tcl b/src/print.tcl
index 4f4e4d0..f5b6df4 100644
--- a/src/print.tcl
+++ b/src/print.tcl
@@ -99,22 +99,13 @@ proc PostScript {} {
}
# set color specific postscript options
- switch -- $ds9(visual) {
- pseudocolor {
- colorbar postscript level $ps(level)
- colorbar postscript colorspace $ps(color)
- colorbar postscript resolution $ps(resolution)
- }
- truecolor {
- colorbar postscript level $ps(level)
- colorbar postscript colorspace $ps(color)
- colorbar postscript resolution $ps(resolution)
-
- colorbarrgb postscript level $ps(level)
- colorbarrgb postscript colorspace $ps(color)
- colorbarrgb postscript resolution $ps(resolution)
- }
- }
+ colorbar postscript level $ps(level)
+ colorbar postscript colorspace $ps(color)
+ colorbar postscript resolution $ps(resolution)
+
+ colorbarrgb postscript level $ps(level)
+ colorbarrgb postscript colorspace $ps(color)
+ colorbarrgb postscript resolution $ps(resolution)
# set frame specific postscript options
foreach f $ds9(frames) {
@@ -193,22 +184,13 @@ proc EPS {fn} {
append options " -file \{$fn\}"
# set color specific postscript options
- switch -- $ds9(visual) {
- pseudocolor {
- colorbar postscript level $level
- colorbar postscript colorspace $color
- colorbar postscript resolution $resolution
- }
- truecolor {
- colorbar postscript level $level
- colorbar postscript colorspace $color
- colorbar postscript resolution $resolution
-
- colorbarrgb postscript level $level
- colorbarrgb postscript colorspace $color
- colorbarrgb postscript resolution $resolution
- }
- }
+ colorbar postscript level $level
+ colorbar postscript colorspace $color
+ colorbar postscript resolution $resolution
+
+ colorbarrgb postscript level $level
+ colorbarrgb postscript colorspace $color
+ colorbarrgb postscript resolution $resolution
# set frame specific postscript options
foreach f $ds9(frames) {
@@ -363,7 +345,7 @@ proc PSPrintDialog {which} {
proc PSPrintBrowse {varname} {
upvar $varname var
- FileLastFull pssavfbox $var
+ FileLast pssavfbox $var
set var [SaveFileDialog pssavfbox]
}
@@ -442,7 +424,7 @@ proc PlotPrintDialog {} {
proc PlotPrintBrowse {varname} {
upvar $varname var
- FileLastFull apsavfbox $var
+ FileLast apsavfbox $var
set var [SaveFileDialog apsavfbox]
}
@@ -508,7 +490,7 @@ proc PRPrintDialog {} {
proc PRPrintBrowse {varname} {
upvar $varname var
- FileLastFull prsavfbox $var
+ FileLast prsavfbox $var
set var [SaveFileDialog prsavfbox]
}
diff --git a/src/stdfbox.tcl b/src/stdfbox.tcl
index 415f81d..f460633 100644
--- a/src/stdfbox.tcl
+++ b/src/stdfbox.tcl
@@ -10,29 +10,12 @@ proc InitDialogBox {} {
global pds9
global env
- switch $ds9(wm) {
- x11 {}
- win32 {set ds9(dialog,dir) [GetEnvHome]}
- aqua {
- switch -- $pds9(dialog) {
- native {}
- motif -
- windows {
- # try to determine if invoked from
- # command line or double click
- if {![info exists env(TERM)]} {
- set ds9(dialog,dir) [GetEnvHome]
- }
- }
- }
- }
- }
-
global fitsurl
set fitsurl {}
global fitsfbox
set fitsfbox(file) {ds9.fits}
+ set fitsfbox(dir) {}
set fitsfbox(types) [list \
[list {FITS} {*.fits}] \
[list {FITS} {*.FITS}] \
@@ -56,6 +39,7 @@ proc InitDialogBox {} {
global savefitsfbox
set savefitsfbox(file) {ds9.fits}
+ set savefitsfbox(dir) {}
set savefitsfbox(types) [list \
[list {FITS} {*.fits}] \
[list {FITS} {*.fit}] \
@@ -68,31 +52,37 @@ proc InitDialogBox {} {
global epsfbox
set epsfbox(file) {ds9.eps}
+ set epsfbox(dir) {}
set epsfbox(types) [list \
[list {EPS} {*.eps}] \
]
global arrayfbox
set arrayfbox(file) {ds9.arr}
+ set arrayfbox(dir) {}
set arrayfbox(types) [list \
[list [::msgcat::mc {Array}] {*.arr}] \
]
global rgbarrayfbox
set rgbarrayfbox(file) {ds9.rgb}
+ set rgbarrayfbox(dir) {}
set rgbarrayfbox(types) [list \
[list [::msgcat::mc {RGB Array}] {*.rgb}] \
]
global nrrdfbox
set nrrdfbox(file) {ds9.nrrd}
+ set nrrdfbox(dir) {}
set nrrdfbox(types) [list \
[list {NRRD} {*.nrrd}] \
]
global envifbox
set envifbox(file) {ds9.hdr}
+ set envifbox(dir) {}
set envifbox(types) [list \
[list {ENVI} {*.hdr}] \
]
global envi2fbox
set envi2fbox(file) {ds9.raw}
+ set envi2fbox(dir) {}
set envi2fbox(types) [list \
[list {ENVI2} {*.bil}] \
[list {ENVI2} {*.bip}] \
@@ -102,28 +92,33 @@ proc InitDialogBox {} {
]
global giffbox
set giffbox(file) {ds9.gif}
+ set giffbox(dir) {}
set giffbox(types) [list \
[list {GIF} {*.gif}] \
]
global jpegfbox
set jpegfbox(file) {ds9.jpeg}
+ set jpegfbox(dir) {}
set jpegfbox(types) [list \
[list {JPEG} {*.jpeg}] \
[list {JPEG} {*.jpg}] \
]
global tifffbox
set tifffbox(file) {ds9.tiff}
+ set tifffbox(dir) {}
set tifffbox(types) [list \
[list {TIFF} {*.tiff}] \
[list {TIFF} {*.tif}] \
]
global pngfbox
set pngfbox(file) {ds9.png}
+ set pngfbox(dir) {}
set pngfbox(types) [list \
[list {PNG} {*.png}] \
]
global mpegfbox
set mpegfbox(file) {ds9.mpeg}
+ set mpegfbox(dir) {}
set mpegfbox(types) [list \
[list {MPEG} {*.mpeg}] \
[list {MPEG} {*.mpg}] \
@@ -131,12 +126,14 @@ proc InitDialogBox {} {
global pixelfbox
set pixelfbox(file) {ds9.pix}
+ set pixelfbox(dir) {}
set pixelfbox(types) [list \
[list {PIX} {*.pix}] \
]
global markerfbox
set markerfbox(file) {ds9.reg}
+ set markerfbox(dir) {}
set markerfbox(types) [list \
[list {REG} {*.reg}] \
[list {FITS} {*.fits}] \
@@ -145,11 +142,13 @@ proc InitDialogBox {} {
global templatefbox
set templatefbox(file) {ds9.tpl}
+ set templatefbox(dir) {}
set templatefbox(types) \
[list [list {TPL} {*.tpl}] [list [::msgcat::mc {All}] {*}] ]
global colorbarfbox
set colorbarfbox(file) {ds9.sao}
+ set colorbarfbox(dir) {}
set colorbarfbox(types) [list \
[list [::msgcat::mc {Colormap}] {*.sao}] \
[list [::msgcat::mc {Colormap}] {*.lut}] \
@@ -157,48 +156,56 @@ proc InitDialogBox {} {
global contrastbiasfbox
set contrastbiasfbox(file) {ds9.cb}
+ set contrastbiasfbox(dir) {}
set contrastbiasfbox(types) [list \
[list {CB} {*.cb}] \
]
global colortagfbox
set colortagfbox(file) {ds9.tag}
+ set colortagfbox(dir) {}
set colortagfbox(types) [list \
[list {Colortag} {*.tag}] \
]
global pssavfbox
set pssavfbox(file) {ds9.ps}
+ set pssavfbox(dir) {}
set pssavfbox(types) [list \
[list {PS} {*.ps}] \
]
global prsavfbox
set prsavfbox(file) {ds9.txt}
+ set prsavfbox(dir) {}
set prsavfbox(types) [list \
[list {TXT} {*.txt}] \
]
global contourfbox
set contourfbox(file) {ds9.con}
+ set contourfbox(dir) {}
set contourfbox(types) [list \
[list {CON} {*.con}] \
]
global contourlevfbox
set contourlevfbox(file) {ds9.lev}
+ set contourlevfbox(dir) {}
set contourlevfbox(types) [list \
[list {LEV} {*.lev}] \
]
global gridfbox
set gridfbox(file) {ds9.grd}
+ set gridfbox(dir) {}
set gridfbox(types) [list \
[list {GRD} {*.grd}] \
]
global catfbox
set catfbox(file) {ds9.cat}
+ set catfbox(dir) {}
set catfbox(types) [list \
[list [::msgcat::mc {Catalog}] {*.cat}] \
[list [::msgcat::mc {Catalog}] {*.rdb}] \
@@ -206,6 +213,7 @@ proc InitDialogBox {} {
global cattsvfbox
set cattsvfbox(file) {ds9.tsv}
+ set cattsvfbox(dir) {}
set cattsvfbox(types) [list \
[list [::msgcat::mc {Catalog}] {*.tsv}] \
[list [::msgcat::mc {Catalog}] {*.csv}] \
@@ -213,6 +221,7 @@ proc InitDialogBox {} {
global catvotfbox
set catvotfbox(file) {ds9.xml}
+ set catvotfbox(dir) {}
set catvotfbox(types) [list \
[list [::msgcat::mc {Catalog}] {*.xml}] \
[list [::msgcat::mc {Catalog}] {*.vot}] \
@@ -221,24 +230,28 @@ proc InitDialogBox {} {
global catfltfbox
set catfltfbox(file) {ds9.flt}
+ set catfltfbox(dir) {}
set catfltfbox(types) [list \
[list {FLT} {*.flt}] \
]
global catsymfbox
set catsymfbox(file) {ds9.sym}
+ set catsymfbox(dir) {}
set catsymfbox(types) [list \
[list {SYM} {*.sym}] \
]
global catcdssrchfbox
set catcdssrchfbox(file) {ds9.cds}
+ set catcdssrchfbox(dir) {}
set catcdssrchfbox(types) [list \
[list {CDS} {*.cds}] \
]
global analysisfbox
set analysisfbox(file) {ds9.ans}
+ set analysisfbox(dir) {}
set analysisfbox(types) [list \
[list [::msgcat::mc {Analysis}] {*.ans}] \
[list [::msgcat::mc {Analysis}] {*.ds9}] \
@@ -246,54 +259,63 @@ proc InitDialogBox {} {
global analysisparamfbox
set analysisparamfbox(file) {}
+ set analysisparamfbox(dir) {}
set analysisparamfbox(types) [list \
]
global apsavfbox
set apsavfbox(file) {ds9.ps}
+ set apsavfbox(dir) {}
set apsavfbox(types) [list \
[list {PS} {*.ps}] \
]
global apdatafbox
set apdatafbox(file) {ds9.dat}
+ set apdatafbox(dir) {}
set apdatafbox(types) [list \
[list {DAT} {*.dat}] \
]
global apconfigfbox
set apconfigfbox(file) {ds9.plt}
+ set apconfigfbox(dir) {}
set apconfigfbox(types) [list \
[list {PLT} {*.plt}] \
]
global textfbox
set textfbox(file) {ds9.txt}
+ set textfbox(dir) {}
set textfbox(types) [list \
[list {TXT} {*.txt}] \
]
global tclfbox
set tclfbox(file) {ds9.tcl}
+ set tclfbox(dir) {}
set tclfbox(types) [list \
[list {TCL} {*.tcl}] \
]
global hvhtmlfbox
set hvhtmlfbox(file) {ds9.html}
- set hvhtmlfbox(types) [list \
+ set hvhtmlfbox(dir) {}
+ set hvhtmlfbox(types) [list \
[list {HTML} {*.html}] \
[list {HTML} {*.htm}] \
]
global wcsfbox
set wcsfbox(file) {ds9.wcs}
+ set wcsfbox(dir) {}
set wcsfbox(types) [list \
[list {WCS} {*.wcs}] \
]
global backupfbox
set backupfbox(file) {ds9.bck}
+ set backupfbox(dir) {}
set backupfbox(types) [list \
[list {BCK} {*.bck}] \
]
@@ -313,6 +335,7 @@ proc SetFileLast {format item} {
global jpegfbox
global pngfbox
global mpegfbox
+
switch $format {
fits {FileLast fitsfbox $item}
eps {FileLast epsfbox $item}
@@ -404,13 +427,13 @@ proc FileDialogMotif {varname which} {
set result [::tk::MotifFDialog $type \
-filetypes $types \
- -initialdir $ds9(dialog,dir) \
+ -initialdir $var(dir) \
-initialfile $var(file) \
-parent $ds9(top)]
if {$result != {}} {
set var(file) [file tail $result]
- set ds9(dialog,dir) [file dirname $result]
+ set var(dir) [file dirname $result]
}
return $result
@@ -434,13 +457,13 @@ proc FileDialogWindows {varname which} {
set result [::tk::dialog::file:: $type \
-filetypes $types \
- -initialdir $ds9(dialog,dir) \
+ -initialdir $var(dir) \
-initialfile $var(file) \
-parent $ds9(top)]
if {$result != {}} {
set var(file) [file tail $result]
- set ds9(dialog,dir) [file dirname $result]
+ set var(dir) [file dirname $result]
}
return $result
@@ -459,13 +482,13 @@ proc FileDialogNative {varname which} {
if [catch {$which \
-filetypes $types \
- -initialdir $ds9(dialog,dir) \
+ -initialdir $var(dir) \
-initialfile $var(file) \
-parent $ds9(top)} result] {
# must have a bad file name, just clear and try again
set var(file) {}
- set ds9(dialog,dir) {}
+ set var(dir) {}
if [catch {$which \
-filetypes $types \
-parent $ds9(top)} result] {
@@ -477,7 +500,7 @@ proc FileDialogNative {varname which} {
if {$result != {}} {
set var(file) [file tail $result]
- set ds9(dialog,dir) [file dirname $result]
+ set var(dir) [file dirname $result]
}
return $result
@@ -486,14 +509,8 @@ proc FileDialogNative {varname which} {
proc FileLast {varname fn} {
upvar #0 $varname var
-
- set var(file) [file tail $fn]
-}
-
-proc FileLastFull {varname fn} {
- upvar #0 $varname var
global ds9
set var(file) [file tail $fn]
- set ds9(dialog,dir) [file dirname $fn]
+ set var(dir) [file dirname $fn]
}
diff --git a/src/util.tcl b/src/util.tcl
index 59c52a8..db74444 100644
--- a/src/util.tcl
+++ b/src/util.tcl
@@ -190,9 +190,10 @@ proc Toplevel {w mb style title proc} {
wm group $w $ds9(top)
wm protocol $w WM_DELETE_WINDOW $proc
- $w configure -menu $mb
+ # we need this first, before the configure command
menu $mb
- AppleMainMenu $mb
+ AppleMenu $mb
+ $w configure -menu $mb
global pds9
if {$pds9(dialog,center)} {
@@ -860,27 +861,28 @@ proc PrefsTheme {} {
switch $pds9(theme) {
native {
switch $ds9(wm) {
- x11 {ttk::style theme use default}
+ x11 {
+ ttk::style theme use default
+ # set bg for non ttk widgets
+ set ds9(app,bg) [ttk::style lookup "." -background]
+
+ option add {*Bbutton.Background} $ds9(app,bg)
+ option add {*Radiobutton.Background} $ds9(app,bg)
+ option add {*Checkbutton.Background} $ds9(app,bg)
+ option add {*Text.Background} $ds9(app,bg)
+ option add {*Listbox.Background} $ds9(app,bg)
+ option add {*Scale.Background} $ds9(app,bg)
+ option add {*Menu.background} $ds9(app,bg)
+ option add {*Table.Background} $ds9(app,bg)
+ option add {*Graph.Background} $ds9(app,bg)
+ option add {*Barchart.Background} $ds9(app,bg)
+ }
win32 {ttk::style theme use xpnative}
aqua {}
}
}
default {ttk::style theme use $pds9(theme)}
}
-
- # set bg for non ttk widgets
- set ds9(app,bg) [ttk::style lookup "." -background]
-
- option add {*Bbutton.Background} $ds9(app,bg)
- option add {*Radiobutton.Background} $ds9(app,bg)
- option add {*Checkbutton.Background} $ds9(app,bg)
- option add {*Text.Background} $ds9(app,bg)
- option add {*Listbox.Background} $ds9(app,bg)
- option add {*Scale.Background} $ds9(app,bg)
- option add {*Menu.background} $ds9(app,bg)
- option add {*Table.Background} $ds9(app,bg)
- option add {*Graph.Background} $ds9(app,bg)
- option add {*Barchart.Background} $ds9(app,bg)
}
proc PrefsDefaultFont {} {
diff --git a/tests/parse.sh b/tests/parse.sh
index 7512350..84b9082 100755
--- a/tests/parse.sh
+++ b/tests/parse.sh
@@ -138,13 +138,15 @@ ds9 fits/wmap.fits[100:200,100:200] &
KillIt
echo ".. hpx[system=equatorial,order=north,layout=equatorial,col=1,quad=1]"
-ds9 fits/wmap.fits[system=equatorial,order=north,layout=equatorial,col=1,quad=1] &
+ds9 fits/wmap.fits[system=equatorial,order=nested,layout=equatorial,col=1,quad=1] &
KillIt
echo ".. nrrd[100:200,100:200]"
-ds9 -nrrd nrrd/float_big_raw.nrrd[100:200,100:200]
+ds9 -nrrd nrrd/float_big_raw.nrrd[100:200,100:200] &
+KillIt
echo ".. envi[100:200,100:200]"
-ds9 -envi envi/float_big.hdr envi/float_big.bsq[100:200,100:200]
+ds9 -envi envi/float_big.hdr envi/float_big.bsq[100:200,100:200] &
+KillIt
echo "DONE"
diff --git a/tlt3.0/Makefile.in b/tlt3.0/Makefile.in
new file mode 100755
index 0000000..e4d16a8
--- /dev/null
+++ b/tlt3.0/Makefile.in
@@ -0,0 +1,449 @@
+# Makefile.in --
+#
+# This file is a Makefile for Sample TEA Extension. If it has the name
+# "Makefile.in" then it is a template for a Makefile; to generate the
+# actual Makefile, run "./configure", which is a configuration script
+# generated by the "autoconf" program (constructs like "@foo@" will get
+# replaced in the actual Makefile.
+#
+# Copyright (c) 1999 Scriptics Corporation.
+# Copyright (c) 2002-2005 ActiveState Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+#========================================================================
+# Add additional lines to handle any additional AC_SUBST cases that
+# have been added in a customized configure script.
+#========================================================================
+
+#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@
+
+#========================================================================
+# Nothing of the variables below this line should need to be changed.
+# Please check the TARGETS section below to make sure the make targets
+# are correct.
+#========================================================================
+
+#========================================================================
+# The names of the source files is defined in the configure script.
+# The object files are used for linking into the final library.
+# This will be used when a dist target is added to the Makefile.
+# It is not important to specify the directory, as long as it is the
+# $(srcdir) or in the generic, win or unix subdirectory.
+#========================================================================
+
+PKG_SOURCES = @PKG_SOURCES@
+PKG_OBJECTS = @PKG_OBJECTS@
+
+PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
+PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
+
+#========================================================================
+# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
+# this package that need to be installed, if any.
+#========================================================================
+
+PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
+
+#========================================================================
+# This is a list of public header files to be installed, if any.
+#========================================================================
+
+PKG_HEADERS = @PKG_HEADERS@
+
+#========================================================================
+# "PKG_LIB_FILE" refers to the library (dynamic or static as per
+# configuration options) composed of the named objects.
+#========================================================================
+
+PKG_LIB_FILE = @PKG_LIB_FILE@
+PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
+
+lib_BINARIES = $(PKG_LIB_FILE)
+BINARIES = $(lib_BINARIES)
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+libdir = @libdir@
+includedir = @includedir@
+datarootdir = @datarootdir@
+datadir = @datadir@
+mandir = @mandir@
+
+DESTDIR =
+
+PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION)
+pkgdatadir = $(datadir)/$(PKG_DIR)
+pkglibdir = $(libdir)/$(PKG_DIR)
+pkgincludedir = $(includedir)/$(PKG_DIR)
+
+top_builddir = .
+
+INSTALL_OPTIONS =
+INSTALL = $(SHELL) $(srcdir)/tclconfig/install-sh -c ${INSTALL_OPTIONS}
+INSTALL_DATA_DIR = ${INSTALL} -d -m 755
+INSTALL_PROGRAM = ${INSTALL} -m 555
+INSTALL_DATA = ${INSTALL} -m 444
+INSTALL_SCRIPT = ${INSTALL_PROGRAM}
+INSTALL_LIBRARY = ${INSTALL_DATA}
+
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+CC = @CC@
+CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
+CFLAGS_WARNING = @CFLAGS_WARNING@
+EXEEXT = @EXEEXT@
+LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
+MAKE_LIB = @MAKE_LIB@
+MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
+MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
+MAKE_STUB_LIB = @MAKE_STUB_LIB@
+OBJEXT = @OBJEXT@
+RANLIB = @RANLIB@
+RANLIB_STUB = @RANLIB_STUB@
+SHLIB_CFLAGS = @SHLIB_CFLAGS@
+SHLIB_LD = @SHLIB_LD@
+SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
+STLIB_LD = @STLIB_LD@
+#TCL_DEFS = @TCL_DEFS@
+TCL_BIN_DIR = @TCL_BIN_DIR@
+TCL_SRC_DIR = @TCL_SRC_DIR@
+TK_BIN_DIR = @TK_BIN_DIR@
+TK_SRC_DIR = @TK_SRC_DIR@
+
+# Not used, but retained for reference of what libs Tcl required
+#TCL_LIBS = @TCL_LIBS@
+
+#========================================================================
+# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
+# package without installing. The other environment variables allow us
+# to test against an uninstalled Tcl. Add special env vars that you
+# require for testing here (like TCLX_LIBRARY).
+#========================================================================
+
+#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
+EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
+TCLLIBPATH = $(top_builddir)
+TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
+PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
+ PATH="$(EXTRA_PATH):$(PATH)" \
+ TCLLIBPATH="$(TCLLIBPATH)"
+
+TCLSH_PROG = @TCLSH_PROG@
+TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG)
+
+WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
+WISH_PROG = @WISH_PROG@
+WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)
+
+SHARED_BUILD = @SHARED_BUILD@
+
+#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@
+INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@ @XFT_CFLAGS@
+
+PKG_CFLAGS = @PKG_CFLAGS@
+
+# TCL_DEFS is not strictly need here, but if you remove it, then you
+# must make sure that configure.in checks for the necessary components
+# that your library may use. TCL_DEFS can actually be a problem if
+# you do not compile with a similar machine setup as the Tcl core was
+# compiled with.
+#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
+DEFS = @DEFS@ $(PKG_CFLAGS)
+
+# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
+CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
+CLEANFILES = @CLEANFILES@
+
+CPPFLAGS = @CPPFLAGS@
+LIBS = @PKG_LIBS@ @LIBS@
+AR = @AR@
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+
+.SUFFIXES: .c .$(OBJEXT)
+
+#========================================================================
+# Start of user-definable TARGETS section
+#========================================================================
+
+#========================================================================
+# TEA TARGETS. Please note that the "libraries:" target refers to platform
+# independent files, and the "binaries:" target includes executable programs and
+# platform-dependent libraries. Modify these targets so that they install
+# the various pieces of your package. The make and install rules
+# for the BINARIES that you specified above have already been done.
+#========================================================================
+
+all: binaries libraries doc
+
+#========================================================================
+# The binaries target builds executable programs, Windows .dll's, unix
+# shared/static libraries, and any other platform-dependent files.
+# The list of targets to build for "binaries:" is specified at the top
+# of the Makefile, in the "BINARIES" variable.
+#========================================================================
+
+binaries: $(BINARIES)
+
+libraries:
+
+#========================================================================
+# Your doc target should differentiate from doc builds (by the developer)
+# and doc installs (see install-doc), which just install the docs on the
+# end user machine when building from source.
+#========================================================================
+
+doc:
+# @echo "If you have documentation to create, place the commands to"
+# @echo "build the docs in the 'doc:' target. For example:"
+# @echo " xml2nroff sample.xml > sample.n"
+# @echo " xml2html sample.xml > sample.html"
+
+install: all install-binaries install-libraries install-doc
+
+install-binaries: binaries install-lib-binaries install-bin-binaries
+
+#========================================================================
+# This rule installs platform-independent files, such as header files.
+# The list=...; for p in $$list handles the empty list case x-platform.
+#========================================================================
+
+install-libraries: libraries
+ @$(INSTALL_DATA_DIR) $(DESTDIR)$(includedir)
+ @echo "Installing header files in $(DESTDIR)$(includedir)"
+ @list='$(PKG_HEADERS)'; for i in $$list; do \
+ echo "Installing $(srcdir)/$$i" ; \
+ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
+ done;
+
+#========================================================================
+# Install documentation. Unix manpages should go in the $(mandir)
+# directory.
+#========================================================================
+
+install-doc: doc
+ @$(INSTALL_DATA_DIR) $(DESTDIR)$(mandir)/mann
+ @echo "Installing documentation in $(DESTDIR)$(mandir)"
+ @list='$(srcdir)/doc/*.n'; for i in $$list; do \
+ echo "Installing $$i"; \
+ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
+ done
+
+test: binaries libraries
+ $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) \
+ -load "package ifneeded ${PACKAGE_NAME} ${PACKAGE_VERSION} \
+ [list load `@CYGPATH@ $(PKG_LIB_FILE)` $(PACKAGE_NAME)]"
+
+shell: binaries libraries
+ @$(TCLSH) $(SCRIPT)
+
+gdb:
+ $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
+
+VALGRINDARGS = --tool=memcheck --num-callers=8 --leak-resolution=high \
+ --leak-check=yes --show-reachable=yes -v
+
+valgrind: binaries libraries
+ $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) \
+ `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
+
+valgrindshell: binaries libraries
+ $(TCLSH_ENV) valgrind $(VALGRINDARGS) $(TCLSH_PROG) $(SCRIPT)
+
+depend:
+
+#========================================================================
+# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
+# mentioned above. That will ensure that this target is built when you
+# run "make binaries".
+#
+# The $(PKG_OBJECTS) objects are created and linked into the final
+# library. In most cases these object files will correspond to the
+# source files above.
+#========================================================================
+
+$(PKG_LIB_FILE): $(PKG_OBJECTS)
+ -rm -f $(PKG_LIB_FILE)
+ ${MAKE_LIB}
+ $(RANLIB) $(PKG_LIB_FILE)
+
+$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
+ -rm -f $(PKG_STUB_LIB_FILE)
+ ${MAKE_STUB_LIB}
+ $(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
+
+#========================================================================
+# We need to enumerate the list of .c to .o lines here.
+#
+# In the following lines, $(srcdir) refers to the toplevel directory
+# containing your extension. If your sources are in a subdirectory,
+# you will have to modify the paths to reflect this:
+#
+# sample.$(OBJEXT): $(srcdir)/generic/sample.c
+# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
+#
+# Setting the VPATH variable to a list of paths will cause the makefile
+# to look into these paths when resolving .c to .obj dependencies.
+# As necessary, add $(srcdir):$(srcdir)/compat:....
+#========================================================================
+
+VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win:$(srcdir)/macosx
+
+.c. at OBJEXT@:
+ $(COMPILE) -c `@CYGPATH@ $<` -o $@
+
+#========================================================================
+# Distribution creation
+# You may need to tweak this target to make it work correctly.
+#========================================================================
+
+#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
+COMPRESS = tar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
+DIST_ROOT = /tmp/dist
+DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
+
+dist-clean:
+ rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
+
+dist: dist-clean
+ $(INSTALL_DATA_DIR) $(DIST_DIR)
+ cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
+ $(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
+ $(DIST_DIR)/
+ chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
+ chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
+
+ for i in $(srcdir)/*.[ch]; do \
+ if [ -f $$i ]; then \
+ cp -p $$i $(DIST_DIR)/ ; \
+ fi; \
+ done;
+
+ $(INSTALL_DATA_DIR) $(DIST_DIR)/tclconfig
+ cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
+ $(DIST_DIR)/tclconfig/
+ chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
+ chmod +x $(DIST_DIR)/tclconfig/install-sh
+
+ list='demos doc generic library mac tests unix win'; \
+ for p in $$list; do \
+ if test -d $(srcdir)/$$p ; then \
+ $(INSTALL_DATA_DIR) $(DIST_DIR)/$$p; \
+ cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
+ fi; \
+ done
+
+ (cd $(DIST_ROOT); $(COMPRESS);)
+
+#========================================================================
+# End of user-definable section
+#========================================================================
+
+#========================================================================
+# Don't modify the file to clean here. Instead, set the "CLEANFILES"
+# variable in configure.in
+#========================================================================
+
+clean:
+ -test -z "$(BINARIES)" || rm -f $(BINARIES)
+ -rm -f *.$(OBJEXT) core *.core
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean: clean
+ -rm -f *.tab.c
+ -rm -f $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log config.status
+
+#========================================================================
+# Install binary object libraries. On Windows this includes both .dll and
+# .lib files. Because the .lib files are not explicitly listed anywhere,
+# we need to deduce their existence from the .dll file of the same name.
+# Library files go into the lib directory.
+# In addition, this will generate the pkgIndex.tcl
+# file in the install location (assuming it can find a usable tclsh shell)
+#
+# You should not have to modify this target.
+#========================================================================
+
+install-lib-binaries: binaries
+ @$(INSTALL_DATA_DIR) $(DESTDIR)$(pkglibdir)
+ @list='$(lib_BINARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
+ $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \
+ stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
+ if test "x$$stub" = "xstub"; then \
+ echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
+ $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
+ else \
+ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
+ $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
+ fi; \
+ ext=`echo $$p|sed -e "s/.*\.//"`; \
+ if test "x$$ext" = "xdll"; then \
+ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
+ if test -f $$lib; then \
+ echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
+ $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
+ fi; \
+ fi; \
+ fi; \
+ done
+ @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
+ if test -f $(srcdir)/$$p; then \
+ destp=`basename $$p`; \
+ echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
+ $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
+ fi; \
+ done
+ @if test "x$(SHARED_BUILD)" = "x1"; then \
+ echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
+ $(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
+ fi
+
+#========================================================================
+# Install binary executables (e.g. .exe files and dependent .dll files)
+# This is for files that must go in the bin directory (located next to
+# wish and tclsh), like dependent .dll files on Windows.
+#
+# You should not have to modify this target, except to define bin_BINARIES
+# above if necessary.
+#========================================================================
+
+install-bin-binaries: binaries
+ @$(INSTALL_DATA_DIR) $(DESTDIR)$(bindir)
+ @list='$(bin_BINARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
+ fi; \
+ done
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+uninstall-binaries:
+ list='$(lib_BINARIES)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(pkglibdir)/$$p; \
+ done
+ list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
+ p=`basename $$p`; \
+ rm -f $(DESTDIR)$(pkglibdir)/$$p; \
+ done
+ list='$(bin_BINARIES)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(bindir)/$$p; \
+ done
+
+.PHONY: all binaries clean depend distclean doc install libraries test
+
+# 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/tlt3.0/aclocal.m4 b/tlt3.0/aclocal.m4
new file mode 100755
index 0000000..1a391a5
--- /dev/null
+++ b/tlt3.0/aclocal.m4
@@ -0,0 +1,96 @@
+#
+# Include the TEA standard macro set
+#
+
+builtin(include,tclconfig/tcl.m4)
+
+#
+# Add here whatever m4 macros you want to define for your package
+#
+
+#--------------------------------------------------------------------
+# SC_PATH_X
+#
+# Locate the X11 header files and the X11 library archive. Try
+# the ac_path_x macro first, but if it doesn't find the X stuff
+# (e.g. because there's no xmkmf program) then check through
+# a list of possible directories. Under some conditions the
+# autoconf macro will return an include directory that contains
+# no include files, so double-check its result just to be safe.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets the following vars:
+# XINCLUDES
+# XLIBSW
+#
+#--------------------------------------------------------------------
+
+AC_DEFUN([SC_PATH_X], [
+ AC_PATH_X
+ not_really_there=""
+ if test "$no_x" = ""; then
+ if test "$x_includes" = ""; then
+ AC_TRY_CPP([#include <X11/XIntrinsic.h>], , not_really_there="yes")
+ else
+ if test ! -r $x_includes/X11/Intrinsic.h; then
+ not_really_there="yes"
+ fi
+ fi
+ fi
+ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
+ AC_MSG_CHECKING([for X11 header files])
+ found_xincludes="no"
+ AC_TRY_CPP([#include <X11/Intrinsic.h>], found_xincludes="yes", found_xincludes="no")
+ if test "$found_xincludes" = "no"; then
+ dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
+ for i in $dirs ; do
+ if test -r $i/X11/Intrinsic.h; then
+ AC_MSG_RESULT([$i])
+ XINCLUDES=" -I$i"
+ found_xincludes="yes"
+ break
+ fi
+ done
+ fi
+ else
+ if test "$x_includes" != ""; then
+ XINCLUDES="-I$x_includes"
+ found_xincludes="yes"
+ fi
+ fi
+ if test "$found_xincludes" = "no"; then
+ AC_MSG_RESULT([couldn't find any!])
+ fi
+
+ if test "$no_x" = yes; then
+ AC_MSG_CHECKING([for X11 libraries])
+ XLIBSW=nope
+ dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
+ for i in $dirs ; do
+ if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
+ AC_MSG_RESULT([$i])
+ XLIBSW="-L$i -lX11"
+ x_libraries="$i"
+ break
+ fi
+ done
+ else
+ if test "$x_libraries" = ""; then
+ XLIBSW=-lX11
+ else
+ XLIBSW="-L$x_libraries -lX11"
+ fi
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_MSG_RESULT([could not find any! Using -lX11.])
+ XLIBSW=-lX11
+ fi
+])
+
diff --git a/tlt3.0/bltBase64.c b/tlt3.0/bltBase64.c
new file mode 100644
index 0000000..dccdd8d
--- /dev/null
+++ b/tlt3.0/bltBase64.c
@@ -0,0 +1,285 @@
+
+/*
+ * bltBase64.c --
+ *
+ * This module implements base64 processing procedures for the BLT toolkit.
+ *
+ * Copyright 1991-2005 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "bltInt.h"
+#include "bltBase64.h"
+
+/*
+ * Table for encoding base64.
+ */
+static char encode64[64] = {
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
+};
+
+/*
+ * Table for decoding base64.
+ *
+ * Note that NUL and '=' also return 0. This is so we can blindly decode 4
+ * octets without requiring special handing of left-over bytes (i.e. when the
+ * encoded buffer did not end on a 3-byte boundary).
+ */
+#define NA 127
+
+static char decode64[256] = {
+ 0 /* '\0' */,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ 62 /* + */,
+ NA, NA, NA,
+ 63 /* / */,
+ 52 /* 0 */, 53 /* 1 */, 54 /* 2 */, 55 /* 3 */, 56 /* 4 */,
+ 57 /* 5 */, 58 /* 6 */, 59 /* 7 */, 60 /* 8 */, 61 /* 9 */,
+ NA, NA, NA,
+ 0 /* = */,
+ NA, NA, NA,
+ 0 /* A */, 1 /* B */, 2 /* C */, 3 /* D */, 4 /* E */,
+ 5 /* F */, 6 /* G */, 7 /* H */, 8 /* I */, 9 /* J */,
+ 10 /* K */, 11 /* L */, 12 /* M */, 13 /* N */, 14 /* O */,
+ 15 /* P */, 16 /* Q */, 17 /* R */, 18 /* S */, 19 /* T */,
+ 20 /* U */, 21 /* V */, 22 /* W */, 23 /* X */, 24 /* Y */,
+ 25 /* Z */,
+ NA, NA, NA, NA, NA, NA,
+ 26 /* a */, 27 /* b */, 28 /* c */, 29 /* d */, 30 /* e */,
+ 31 /* f */, 32 /* g */, 33 /* h */, 34 /* i */, 35 /* j */,
+ 36 /* k */, 37 /* l */, 38 /* m */, 39 /* n */, 40 /* o */,
+ 41 /* p */, 42 /* q */, 43 /* r */, 44 /* s */, 45 /* t */,
+ 46 /* u */, 47 /* v */, 48 /* w */, 49 /* x */, 50 /* y */,
+ 51 /* z */,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
+ NA, NA, NA, NA, NA
+};
+
+int
+Blt_IsBase64(const unsigned char *bytes, size_t nBytes)
+{
+ const unsigned char *bp, *bend;
+
+ for (bp = bytes, bend = bp + nBytes; bp < bend; bp++) {
+ unsigned int byte;
+
+ byte = *bp;
+ if ((decode64[byte] == NA) && (!isspace(byte))) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static INLINE unsigned char
+NextChar(const unsigned char **bp, const unsigned char *lastPtr)
+{
+ char c;
+
+ /* Skip whitespace and invalid characters. Let's see if being fault-tolerant
+ * is better than erroring out here.*/
+ while (((*bp) < lastPtr) && (decode64[(**bp)] == NA)) {
+ (*bp)++;
+ }
+ c = ((*bp) < lastPtr) ? **bp : 0;
+ if ((c != '\0') && (c != '=')) {
+ (*bp)++;
+ }
+ return c; /* Valid symbol */
+}
+
+unsigned char *
+Blt_Base64_Decode(Tcl_Interp *interp, const char *string, size_t *lengthPtr)
+{
+ size_t nBytes;
+ unsigned char *bp;
+ unsigned char *buffer;
+ const unsigned char *p, *pend;
+ nBytes = *lengthPtr;
+
+ /*
+ * Assuming that the string contains no padding or whitespace, allocate a
+ * buffer with a worst-case length.
+ */
+ nBytes = ((nBytes + 1) * 3) / 4;
+ buffer = malloc(nBytes);
+ if (buffer == NULL) {
+ Tcl_AppendResult(interp, "can't allocate ", Blt_Itoa(nBytes),
+ " for buffer", (char *)NULL);
+ return NULL;
+ }
+ bp = buffer;
+ for (p = (unsigned char *)string, pend = p + *lengthPtr; p < pend;
+ /*empty*/) {
+ unsigned char a, b, c, d;
+ unsigned int u1, u2, u3;
+
+ a = NextChar(&p, pend);
+ b = NextChar(&p, pend);
+ c = NextChar(&p, pend);
+ d = NextChar(&p, pend);
+
+ if (d == '\0') {
+ if (a != '\0') {
+ Tcl_AppendResult(interp, "premature end of base64 data",
+ (char *)NULL);
+ free(buffer);
+ return NULL;
+ }
+ break;
+ }
+
+ /*
+ * in: a b c d
+ * ------.......-------......
+ * |54321054|32105432|10543210|
+ * out: u1 u2 u3
+ */
+
+ /* a = [543210xx] | [xxxxxx54] >> 4 */
+ u1 = (decode64[a] << 2) | ((decode64[b] & 0x30) >> 4);
+ /* b = [3210xxxx] | [xxxx5432] */
+ u2 = ((decode64[b] & 0x0F) << 4) |((decode64[c] & 0x3C) >> 2);
+ /* c = [10xxxxxx] | [xx543210] */
+ u3 = ((decode64[c] & 0x03) << 6) | decode64[d];
+
+ if (d == '=') {
+ if ((a == '=') || (b == '=')) {
+ break; /* This should not be possible. */
+ }
+ if (c == '=') {
+ *bp++ = (unsigned char)u1;
+ } else {
+ *bp++ = (unsigned char)u1;
+ *bp++ = (unsigned char)u2;
+ }
+ break;
+ }
+ bp[0] = (unsigned char)u1;
+ bp[1] = (unsigned char)u2;
+ bp[2] = (unsigned char)u3;
+ bp += 3;
+ }
+ nBytes = bp - buffer;
+ /* Reset the fill point to the number of bytes processed. */
+ *lengthPtr = nBytes;
+ return buffer;
+}
+
+char *
+Blt_Base64_Encode(Tcl_Interp *interp, const unsigned char *buffer,
+ size_t bufsize)
+{
+ char *dest, *dp;
+ int count, remainder;
+ size_t length;
+ const unsigned char *sp, *send;
+
+ /* Compute worst-case length. */
+ length = (((bufsize + 1) * 4) + 2) / 3;
+ length += (length + 59) / 60; /* Add space for newlines. */
+ length++; /* NUL byte */
+
+ dest = malloc(sizeof(char) * length);
+ if (dest == NULL) {
+ Tcl_AppendResult(interp, "can't allocate \"", Blt_Itoa(length),
+ "\" bytes for buffer", (char *)NULL);
+ return NULL;
+ }
+ count = 0;
+ remainder = bufsize % 3;
+ send = buffer + (bufsize - remainder);
+ dp = dest;
+ for (sp = buffer; sp < send; sp += 3) {
+ int a, b, c, d;
+
+ /*
+ * in: 0 1 2
+ * |76543210|76543210|76543210|
+ * ------.......-------......
+ * out: a b c d
+ */
+ /* a = [xx765432] */
+ a = sp[0] >> 2;
+ /* b = [xx10xxxx] | [xxxx7654] */
+ b = ((sp[0] & 0x03) << 4) | ((sp[1] & 0xF0) >> 4);
+ /* c = [xx3210xx] | [xxxxxx76] */
+ c = ((sp[1] & 0x0F) << 2) | ((sp[2] & 0xC0) >> 6);
+ /* d = [xx543210] */
+ d = (sp[2] & 0x3F);
+
+ dp[0] = encode64[a];
+ dp[1] = encode64[b];
+ dp[2] = encode64[c];
+ dp[3] = encode64[d];
+
+ dp += 4;
+ count += 4;
+ if (count > 60) {
+ *dp++ = '\n';
+ count = 0;
+ }
+ }
+
+ if (remainder > 0) {
+ int a, b, c;
+
+ /*
+ * Handle the two cases where the input buffer doesn't end on a 3-byte
+ * boundary.
+ */
+ if (remainder == 2) {
+ a = sp[0] >> 2;
+ b = ((sp[0] & 0x03) << 4) | ((sp[1] & 0xF0) >> 4);
+ c = ((sp[1] & 0x0F) << 2);
+ dp[0] = encode64[a];
+ dp[1] = encode64[b];
+ dp[2] = encode64[c];
+ dp[3] = '=';
+ } else if (remainder == 1) {
+ a = sp[0] >> 2;
+ b = ((sp[0] & 0x03) << 4);
+ dp[0] = encode64[a];
+ dp[1] = encode64[b];
+ dp[2] = dp[3] = '=';
+ }
+ dp += 4;
+ count += 4;
+ if (count > 60) {
+ *dp++ = '\n';
+ }
+ }
+ assert((size_t)(dp - dest) < length);
+ *dp = '\0';
+ return dest;
+}
+
diff --git a/tlt3.0/bltBase64.h b/tlt3.0/bltBase64.h
new file mode 100644
index 0000000..6dad753
--- /dev/null
+++ b/tlt3.0/bltBase64.h
@@ -0,0 +1,39 @@
+/*
+ * bltBase64.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_BASE64_H
+#define _BLT_BASE64_H
+
+#include <tcl.h>
+
+extern unsigned char *Blt_Base64_Decode(Tcl_Interp *interp,
+ const char *string, size_t *lengthPtr);
+
+extern char *Blt_Base64_Encode(Tcl_Interp *interp,
+ const unsigned char *buffer, size_t bufsize);
+
+extern int Blt_IsBase64(const unsigned char *buf, size_t length);
+
+#endif
diff --git a/tlt3.0/bltBgStyle.c b/tlt3.0/bltBgStyle.c
new file mode 100644
index 0000000..b866495
--- /dev/null
+++ b/tlt3.0/bltBgStyle.c
@@ -0,0 +1,2018 @@
+/*
+ * bltBgPattern.c --
+ *
+ * This module creates background patterns for the BLT toolkit.
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltWindow.h"
+#include "bltMath.h"
+#include "bltChain.h"
+#include "bltImage.h"
+#include "bltHash.h"
+#include "bltBgStyle.h"
+
+#define BG_PATTERN_THREAD_KEY "BLT Background Pattern Data"
+#define TEXTURE_CHECKERED 1
+#define TEXTURE_STRIPED 0
+
+enum PatternTypes {
+ PATTERN_GRADIENT, /* Color gradient. */
+ PATTERN_TILE, /* Tiled or resizable color picture. */
+ PATTERN_SOLID, /* General pattern. */
+ PATTERN_TEXTURE, /* Procedural texture. */
+};
+
+
+enum ReferenceTypes {
+ REFERENCE_SELF, /* Current window. */
+ REFERENCE_TOPLEVEL, /* Toplevel of current window. */
+ REFERENCE_WINDOW, /* Specifically named window. */
+ REFERENCE_NONE, /* Don't use reference
+ * window. Background region will be
+ * defined by user. */
+};
+
+typedef struct {
+ int x, y;
+ unsigned int w, h;
+ Tk_Window tkwin;
+} Reference;
+
+typedef struct {
+ int x, y, width, height;
+} BgRegion;
+
+typedef struct {
+ Blt_HashTable patternTable; /* Hash table of pattern structures
+ * keyed by the name of the image. */
+ Tcl_Interp *interp; /* Interpreter associated with this set
+ * of background patterns. */
+ int nextId; /* Serial number of the identifier to be
+ * used for next background pattern
+ * created. */
+} BackgroundInterpData;
+
+typedef struct _Pattern Pattern;
+
+typedef void (DestroyPatternProc)(Pattern *patternPtr);
+typedef int (ConfigurePatternProc)(Tcl_Interp *interp, Pattern *patternPtr,
+ int objc, Tcl_Obj *const *objv, unsigned int flags);
+typedef void (DrawRectangleProc)(Tk_Window tkwin, Drawable drawable,
+ Pattern *patternPtr, int x, int y, int w, int h);
+typedef void (DrawPolygonProc)(Tk_Window tkwin, Drawable drawable,
+ Pattern *patternPtr, int nPoints, XPoint *points);
+
+typedef struct {
+ enum PatternTypes type; /* Type of pattern style: solid, tile,
+ * texture, or gradient. */
+ Blt_ConfigSpec *configSpecs;
+ DestroyPatternProc *destroyProc;
+ ConfigurePatternProc *configProc;
+ DrawRectangleProc *drawRectangleProc;
+ DrawPolygonProc *drawPolygonProc;
+} PatternClass;
+
+
+struct _Pattern {
+ const char *name; /* Generated name of background
+ * pattern. */
+ PatternClass *classPtr;
+ BackgroundInterpData *dataPtr;
+ Tk_Window tkwin; /* Main window. Used to query background
+ * pattern options. */
+ Display *display; /* Display of this background
+ * pattern. */
+ unsigned int flags; /* See definitions below. */
+ Blt_HashEntry *hashPtr; /* Hash entry in pattern table. */
+ Blt_Chain chain; /* List of pattern tokens. Used to
+ * register callbacks for each client of
+ * the background pattern. */
+ Blt_ChainLink link; /* Background token that is associated
+ * with the pattern creation "bgpattern
+ * create...". */
+ Tk_3DBorder border; /* 3D Border. May be used for all
+ * background types. */
+ Tk_Window refWindow; /* Refer to coordinates in this window
+ * when determining the tile/gradient
+ * origin. */
+ BgRegion refRegion;
+ Blt_HashTable pictTable; /* Table of pictures cached for each
+ * pattern reference. */
+ int reference; /* "self", "toplevel", or "window". */
+ int xOrigin, yOrigin;
+};
+
+typedef struct {
+ const char *name; /* Generated name of background
+ * pattern. */
+ PatternClass *classPtr;
+ BackgroundInterpData *dataPtr;
+ Tk_Window tkwin; /* Main window. Used to query background
+ * pattern options. */
+ Display *display; /* Display of this background
+ * pattern. */
+ unsigned int flags; /* See definitions below. */
+ Blt_HashEntry *hashPtr; /* Link to original client. */
+ Blt_Chain chain; /* List of pattern tokens. Used to
+ * register callbacks for each client of
+ * the background pattern. */
+ Blt_ChainLink link; /* Background token that is associated
+ * with the pattern creation "bgpattern
+ * create...". */
+ Tk_3DBorder border; /* 3D Border. May be used for all
+ * pattern types. */
+ Tk_Window refWindow; /* Refer to coordinates in this window
+ * when determining the tile/gradient
+ * origin. */
+ BgRegion refRegion;
+ Blt_HashTable pictTable; /* Table of pictures cached for each
+ * pattern reference. */
+ int reference; /* "self", "toplevel", or "window". */
+ int xOrigin, yOrigin;
+
+ /* Solid pattern specific fields. */
+ int alpha; /* Transparency value. */
+} SolidPattern;
+
+typedef struct {
+ const char *name; /* Generated name of background
+ * pattern. */
+ PatternClass *classPtr;
+ BackgroundInterpData *dataPtr;
+ Tk_Window tkwin; /* Main window. Used to query background
+ * pattern options. */
+ Display *display; /* Display of this background
+ * pattern. */
+ unsigned int flags; /* See definitions below. */
+ Blt_HashEntry *hashPtr; /* Link to original client. */
+ Blt_Chain chain; /* List of pattern tokens. Used to
+ * register callbacks for each client of
+ * the background pattern. */
+ Blt_ChainLink link; /* Background token that is associated
+ * with the pattern creation "bgpattern
+ * create...". */
+ Tk_3DBorder border; /* 3D Border. May be used for all
+ * pattern types. */
+ Tk_Window refWindow; /* Refer to coordinates in this window
+ * when determining the tile/gradient
+ * origin. */
+ BgRegion refRegion;
+ Blt_HashTable pictTable; /* Table of pictures cached for each
+ * pattern reference. */
+ int reference; /* "self", "toplevel", or "window". */
+ int xOrigin, yOrigin;
+ /* Image pattern specific fields. */
+ Tk_Image tkImage; /* Original image (before
+ * resampling). */
+} TilePattern;
+
+typedef struct {
+ const char *name; /* Generated name of background
+ * pattern. */
+ PatternClass *classPtr;
+ BackgroundInterpData *dataPtr;
+ Tk_Window tkwin; /* Main window. Used to query background
+ * pattern options. */
+ Display *display; /* Display of this background
+ * pattern. */
+ unsigned int flags; /* See definitions below. */
+ Blt_HashEntry *hashPtr; /* Link to original client. */
+ Blt_Chain chain; /* List of pattern tokens. Used to
+ * register callbacks for each client of
+ * the background pattern. */
+ Blt_ChainLink link; /* Background token that is associated
+ * with the pattern creation "bgpattern
+ * create...". */
+ Tk_3DBorder border; /* 3D Border. May be used for all
+ * pattern types. */
+ Tk_Window refWindow; /* Refer to coordinates in this window
+ * when determining the tile/gradient
+ * origin. */
+ BgRegion refRegion;
+ Blt_HashTable pictTable; /* Table of pictures cached for each
+ * pattern reference. */
+ int reference; /* "self", "toplevel", or "window". */
+ int xOrigin, yOrigin;
+ /* Gradient pattern specific fields. */
+ int alpha; /* Transparency value. */
+} GradientPattern;
+
+typedef struct {
+ const char *name; /* Generated name of background
+ * pattern. */
+ PatternClass *classPtr;
+ BackgroundInterpData *dataPtr;
+ Tk_Window tkwin; /* Main window. Used to query background
+ * pattern options. */
+ Display *display; /* Display of this background
+ * pattern. */
+ unsigned int flags; /* See definitions below. */
+ Blt_HashEntry *hashPtr; /* Link to original client. */
+ Blt_Chain chain; /* List of pattern tokens. Used to
+ * register callbacks for each client of
+ * the background pattern. */
+ Blt_ChainLink link; /* Background token that is associated
+ * with the pattern creation "bgpattern
+ * create...". */
+ Tk_3DBorder border; /* 3D Border. May be used for all
+ * pattern types. */
+ Tk_Window refWindow; /* Refer to coordinates in this window
+ * when determining the tile/gradient
+ * origin. */
+ BgRegion refRegion;
+ Blt_HashTable pictTable; /* Table of pictures cached for each
+ * pattern reference. */
+ int reference; /* "self", "toplevel", or "window". */
+ int xOrigin, yOrigin;
+
+ /* Texture pattern specific fields. */
+ int alpha; /* Transparency value. */
+ int type;
+} TexturePattern;
+
+struct _Blt_Background {
+ Pattern *corePtr; /* Pointer to master background pattern
+ * object. */
+ Blt_BackgroundChangedProc *notifyProc;
+ ClientData clientData; /* Data to be passed on notifier
+ * callbacks. */
+ Blt_ChainLink link; /* Entry in notifier list. */
+};
+
+#define DELETE_PENDING (1<<0)
+#define BG_CENTER (1<<2)
+#define BG_SCALE (1<<3)
+
+typedef struct _Blt_Background Background;
+
+#define DEF_OPACITY "100.0"
+#define DEF_ORIGIN_X "0"
+#define DEF_ORIGIN_Y "0"
+#define DEF_BORDER STD_NORMAL_BACKGROUND
+#define DEF_GRADIENT_PATH "y"
+#define DEF_GRADIENT_HIGH "grey90"
+#define DEF_GRADIENT_JITTER "no"
+#define DEF_GRADIENT_LOGSCALE "yes"
+#define DEF_GRADIENT_LOW "grey50"
+#define DEF_GRADIENT_MODE "xlinear"
+#define DEF_GRADIENT_SHAPE "linear"
+#define DEF_REFERENCE "toplevel"
+#define DEF_RESAMPLE_FILTER "box"
+#define DEF_SCALE "no"
+#define DEF_CENTER "no"
+#define DEF_TILE "no"
+
+static Blt_OptionParseProc ObjToImageProc;
+static Blt_OptionPrintProc ImageToObjProc;
+static Blt_OptionFreeProc FreeImageProc;
+static Blt_CustomOption imageOption =
+ {
+ ObjToImageProc, ImageToObjProc, FreeImageProc, (ClientData)0
+ };
+
+extern Blt_CustomOption bltFilterOption;
+
+static Blt_OptionParseProc ObjToReferenceProc;
+static Blt_OptionPrintProc ReferenceToObjProc;
+static Blt_CustomOption referenceToOption =
+ {
+ ObjToReferenceProc, ReferenceToObjProc, NULL, (ClientData)0
+ };
+
+static Blt_OptionParseProc ObjToOpacityProc;
+static Blt_OptionPrintProc OpacityToObjProc;
+static Blt_CustomOption opacityOption =
+ {
+ ObjToOpacityProc, OpacityToObjProc, NULL, (ClientData)0
+ };
+
+static Blt_OptionParseProc ObjToTypeProc;
+static Blt_OptionPrintProc TypeToObjProc;
+static Blt_CustomOption typeOption =
+ {
+ ObjToTypeProc, TypeToObjProc, NULL, (ClientData)0
+ };
+
+static Blt_ConfigSpec solidConfigSpecs[] =
+ {
+ {BLT_CONFIG_SYNONYM, "-background", "color", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_SYNONYM, "-bg", "color", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_BORDER, "-color", "color", "Color", DEF_BORDER,
+ Blt_Offset(SolidPattern, border), 0},
+ {BLT_CONFIG_CUSTOM, "-opacity", "opacity", "Opacity", "100.0",
+ Blt_Offset(SolidPattern, alpha), BLT_CONFIG_DONT_SET_DEFAULT,
+ &opacityOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+ };
+
+static Blt_ConfigSpec tileConfigSpecs[] =
+ {
+ {BLT_CONFIG_BITMASK, "-center", "center", "Center", DEF_CENTER,
+ Blt_Offset(TilePattern, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)BG_CENTER},
+ {BLT_CONFIG_BORDER, "-color", "color", "Color", DEF_BORDER,
+ Blt_Offset(TilePattern, border), 0},
+ {BLT_CONFIG_BORDER, "-darkcolor", "darkColor", "DarkColor", DEF_BORDER,
+ Blt_Offset(TilePattern, border), 0},
+ {BLT_CONFIG_CUSTOM, "-image", "image", "Image", (char *)NULL,
+ Blt_Offset(TilePattern, tkImage), BLT_CONFIG_DONT_SET_DEFAULT,
+ &imageOption},
+ {BLT_CONFIG_BORDER, "-lightcolor", "lightColor", "LightColor", DEF_BORDER,
+ Blt_Offset(TilePattern, border), 0},
+ {BLT_CONFIG_CUSTOM, "-relativeto", "relativeTo", "RelativeTo",
+ DEF_REFERENCE, Blt_Offset(TilePattern, reference),
+ BLT_CONFIG_DONT_SET_DEFAULT, &referenceToOption},
+ {BLT_CONFIG_BITMASK, "-scale", "scale", "scale", DEF_SCALE,
+ Blt_Offset(TilePattern, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)BG_SCALE},
+ {BLT_CONFIG_PIXELS, "-xorigin", "xOrigin", "XOrigin", DEF_ORIGIN_X,
+ Blt_Offset(TilePattern, xOrigin), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yorigin", "yOrigin", "YOrigin", DEF_ORIGIN_Y,
+ Blt_Offset(TilePattern, yOrigin), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+ };
+
+static Blt_ConfigSpec gradientConfigSpecs[] =
+ {
+ {BLT_CONFIG_BORDER, "-background", "background", "Background", DEF_BORDER,
+ Blt_Offset(GradientPattern, border), 0},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-opacity", "opacity", "Opacity", "100.0",
+ Blt_Offset(GradientPattern, alpha), BLT_CONFIG_DONT_SET_DEFAULT,
+ &opacityOption},
+ {BLT_CONFIG_CUSTOM, "-relativeto", "relativeTo", "RelativeTo",
+ DEF_REFERENCE, Blt_Offset(GradientPattern, reference),
+ BLT_CONFIG_DONT_SET_DEFAULT, &referenceToOption},
+ {BLT_CONFIG_PIXELS, "-xorigin", "xOrigin", "XOrigin", DEF_ORIGIN_X,
+ Blt_Offset(GradientPattern, xOrigin), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yorigin", "yOrigin", "YOrigin", DEF_ORIGIN_Y,
+ Blt_Offset(GradientPattern, yOrigin), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+ };
+
+static Blt_ConfigSpec textureConfigSpecs[] =
+ {
+ {BLT_CONFIG_BORDER, "-background", "background", "Background", DEF_BORDER,
+ Blt_Offset(TexturePattern, border), 0},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-relativeto", "relativeTo", "RelativeTo",
+ DEF_REFERENCE, Blt_Offset(TexturePattern, reference),
+ BLT_CONFIG_DONT_SET_DEFAULT, &referenceToOption},
+ {BLT_CONFIG_CUSTOM, "-type", "type", "Type",
+ DEF_REFERENCE, Blt_Offset(TexturePattern, type),
+ BLT_CONFIG_DONT_SET_DEFAULT, &typeOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+ };
+
+static void NotifyClients(Pattern *corePtr);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ImageChangedProc
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+ImageChangedProc(
+ ClientData clientData,
+ int x, int y, int width, int height, /* Not used. */
+ int imageWidth, int imageHeight) /* Not used. */
+{
+ Pattern *corePtr = clientData;
+
+ /* Propagate the change in the image to all the clients. */
+ NotifyClients(corePtr);
+}
+
+/*ARGSUSED*/
+static void
+FreeImageProc(
+ ClientData clientData,
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ TilePattern *patternPtr = (TilePattern *)(widgRec);
+
+ if (patternPtr->tkImage != NULL) {
+ Tk_FreeImage(patternPtr->tkImage);
+ patternPtr->tkImage = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToImageProc --
+ *
+ * Given an image name, get the Tk image associated with it.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToImageProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representation of value. */
+ char *widgRec, /* Widget record. */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ TilePattern *patternPtr = (TilePattern *)(widgRec);
+ Tk_Image tkImage;
+
+ tkImage = Tk_GetImage(interp, patternPtr->tkwin, Tcl_GetString(objPtr),
+ ImageChangedProc, patternPtr);
+ if (tkImage == NULL) {
+ return TCL_ERROR;
+ }
+ patternPtr->tkImage = tkImage;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ImageToObjProc --
+ *
+ * Convert the image name into a string Tcl_Obj.
+ *
+ * Results:
+ * The string representation of the image is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ImageToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ TilePattern *patternPtr = (TilePattern *)(widgRec);
+
+ if (patternPtr->tkImage == NULL) {
+ return Tcl_NewStringObj("", -1);
+ }
+ return Tcl_NewStringObj(Blt_Image_Name(patternPtr->tkImage), -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToReference --
+ *
+ * Given a string name, get the resample filter associated with it.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToReferenceProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representation of value. */
+ char *widgRec, /* Widget record. */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ Pattern *patternPtr = (Pattern *)(widgRec);
+ int *referencePtr = (int *)(widgRec + offset);
+ const char *string;
+ char c;
+ int refType;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 's') && (strncmp(string, "self", length) == 0)) {
+ refType = REFERENCE_SELF;
+ } else if ((c == 't') && (strncmp(string, "toplevel", length) == 0)) {
+ refType = REFERENCE_TOPLEVEL;
+ } else if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
+ refType = REFERENCE_NONE;
+ } else if (c == '.') {
+ Tk_Window tkwin, tkMain;
+
+ tkMain = Tk_MainWindow(interp);
+ tkwin = Tk_NameToWindow(interp, string, tkMain);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ refType = REFERENCE_WINDOW;
+ patternPtr->refWindow = tkwin;
+ } else {
+ Tcl_AppendResult(interp, "unknown reference type \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ *referencePtr = refType;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ReferenceToObjProc --
+ *
+ * Convert the picture filter into a string Tcl_Obj.
+ *
+ * Results:
+ * The string representation of the filter is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ReferenceToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int reference = *(int *)(widgRec + offset);
+ const char *string;
+
+ switch (reference) {
+ case REFERENCE_SELF:
+ string = "self";
+ break;
+
+ case REFERENCE_TOPLEVEL:
+ string = "toplevel";
+ break;
+
+ case REFERENCE_NONE:
+ string = "none";
+ break;
+
+ case REFERENCE_WINDOW:
+ {
+ Pattern *patternPtr = (Pattern *)(widgRec);
+
+ string = Tk_PathName(patternPtr->refWindow);
+ }
+ break;
+
+ default:
+ string = "???";
+ break;
+ }
+ return Tcl_NewStringObj(string, -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToOpacity --
+ *
+ * Given a string name, get the resample filter associated with it.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToOpacityProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representation of value. */
+ char *widgRec, /* Widget record. */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int *alphaPtr = (int *)(widgRec + offset);
+ double opacity;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &opacity) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((opacity < 0.0) || (opacity > 100.0)) {
+ Tcl_AppendResult(interp, "invalid percent opacity \"",
+ Tcl_GetString(objPtr), "\" should be 0 to 100", (char *)NULL);
+ return TCL_ERROR;
+ }
+ opacity = (opacity / 100.0) * 255.0;
+ *alphaPtr = ROUND(opacity);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OpacityToObj --
+ *
+ * Convert the picture filter into a string Tcl_Obj.
+ *
+ * Results:
+ * The string representation of the filter is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+OpacityToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int *alphaPtr = (int *)(widgRec + offset);
+ double opacity;
+
+ opacity = (*alphaPtr / 255.0) * 100.0;
+ return Tcl_NewDoubleObj(opacity);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToTypeProc --
+ *
+ * Translate the given string to the gradient shape is represents. Value
+ * shapes are "linear", "bilinear", "radial", and "rectangular".
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToTypeProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representation of value. */
+ char *widgRec, /* Widget record. */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int *typePtr = (int *)(widgRec + offset);
+ char *string;
+
+ string = Tcl_GetString(objPtr);
+ if (strcmp(string, "striped") == 0) {
+ *typePtr = TEXTURE_STRIPED;
+ } else if (strcmp(string, "checkered") == 0) {
+ *typePtr = TEXTURE_CHECKERED;
+ } else {
+ Tcl_AppendResult(interp, "unknown pattern type \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TypeToObjProc --
+ *
+ * Returns the string representing the current pattern type.
+ *
+ * Results:
+ * The string representation of the pattern is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+TypeToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int type = *(int *)(widgRec + offset);
+ const char *string;
+
+ switch (type) {
+ case TEXTURE_STRIPED:
+ string = "striped";
+ break;
+
+ case TEXTURE_CHECKERED:
+ string = "checkered";
+ break;
+
+ default:
+ string = "???";
+ }
+ return Tcl_NewStringObj(string, -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NotifyClients --
+ *
+ * Notify each client that the background pattern has changed.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+NotifyClients(Pattern *patternPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(patternPtr->chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Background *bgPtr;
+
+ /* Notify each client that the background pattern has changed. The
+ * client should schedule itself for redrawing. */
+ bgPtr = Blt_Chain_GetValue(link);
+ if (bgPtr->notifyProc != NULL) {
+ (*bgPtr->notifyProc)(bgPtr->clientData);
+ }
+ }
+}
+
+/*
+ * The following routines are directly from tk3d.c.
+ *
+ * tk3d.c --
+ *
+ * This module provides procedures to draw borders in
+ * the three-dimensional Motif style.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * They fix a problem in the Intersect procedure when the polygon is big (e.q
+ * 1600x1200). The computation overflows the 32-bit integers used.
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ShiftLine --
+ *
+ * Given two points on a line, compute a point on a new line that is
+ * parallel to the given line and a given distance away from it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ShiftLine(
+ XPoint *p, /* First point on line. */
+ XPoint *q, /* Second point on line. */
+ int distance, /* New line is to be this many units
+ * to the left of original line, when
+ * looking from p1 to p2. May be
+ * negative. */
+ XPoint *r) /* Store coords of point on new line
+ * here. */
+{
+ int dx, dy, dxNeg, dyNeg;
+
+ /*
+ * The table below is used for a quick approximation in computing the new
+ * point. An index into the table is 128 times the slope of the original
+ * line (the slope must always be between 0 and 1). The value of the
+ * table entry is 128 times the amount to displace the new line in y for
+ * each unit of perpendicular distance. In other words, the table maps
+ * from the tangent of an angle to the inverse of its cosine. If the
+ * slope of the original line is greater than 1, then the displacement is
+ * done in x rather than in y.
+ */
+ static int shiftTable[129];
+
+ /*
+ * Initialize the table if this is the first time it is
+ * used.
+ */
+
+ if (shiftTable[0] == 0) {
+ int i;
+ double tangent, cosine;
+
+ for (i = 0; i <= 128; i++) {
+ tangent = i/128.0;
+ cosine = 128/cos(atan(tangent)) + .5;
+ shiftTable[i] = (int) cosine;
+ }
+ }
+
+ *r = *p;
+ dx = q->x - p->x;
+ dy = q->y - p->y;
+ if (dy < 0) {
+ dyNeg = 1;
+ dy = -dy;
+ } else {
+ dyNeg = 0;
+ }
+ if (dx < 0) {
+ dxNeg = 1;
+ dx = -dx;
+ } else {
+ dxNeg = 0;
+ }
+ if (dy <= dx) {
+ dy = ((distance * shiftTable[(dy<<7)/dx]) + 64) >> 7;
+ if (!dxNeg) {
+ dy = -dy;
+ }
+ r->y += dy;
+ } else {
+ dx = ((distance * shiftTable[(dx<<7)/dy]) + 64) >> 7;
+ if (dyNeg) {
+ dx = -dx;
+ }
+ r->x += dx;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------------
+ *
+ * Intersect --
+ *
+ * Find the intersection point between two lines.
+ *
+ * Results:
+ * Under normal conditions 0 is returned and the point at *iPtr is filled
+ * in with the intersection between the two lines. If the two lines are
+ * parallel, then -1 is returned and *iPtr isn't modified.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------------
+ */
+static int
+Intersect(a1Ptr, a2Ptr, b1Ptr, b2Ptr, iPtr)
+ XPoint *a1Ptr; /* First point of first line. */
+ XPoint *a2Ptr; /* Second point of first line. */
+ XPoint *b1Ptr; /* First point of second line. */
+ XPoint *b2Ptr; /* Second point of second line. */
+ XPoint *iPtr; /* Filled in with intersection point. */
+{
+ float dxadyb, dxbdya, dxadxb, dyadyb, p, q;
+
+ /*
+ * The code below is just a straightforward manipulation of two
+ * equations of the form y = (x-x1)*(y2-y1)/(x2-x1) + y1 to solve
+ * for the x-coordinate of intersection, then the y-coordinate.
+ */
+
+ dxadyb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->y - b1Ptr->y);
+ dxbdya = (b2Ptr->x - b1Ptr->x)*(a2Ptr->y - a1Ptr->y);
+ dxadxb = (a2Ptr->x - a1Ptr->x)*(b2Ptr->x - b1Ptr->x);
+ dyadyb = (a2Ptr->y - a1Ptr->y)*(b2Ptr->y - b1Ptr->y);
+
+ if (dxadyb == dxbdya) {
+ return -1;
+ }
+ p = (a1Ptr->x*dxbdya - b1Ptr->x*dxadyb + (b1Ptr->y - a1Ptr->y)*dxadxb);
+ q = dxbdya - dxadyb;
+ if (q < 0) {
+ p = -p;
+ q = -q;
+ }
+ if (p < 0) {
+ iPtr->x = - ((-p + q/2)/q);
+ } else {
+ iPtr->x = (p + q/2)/q;
+ }
+ p = (a1Ptr->y*dxadyb - b1Ptr->y*dxbdya + (b1Ptr->x - a1Ptr->x)*dyadyb);
+ q = dxadyb - dxbdya;
+ if (q < 0) {
+ p = -p;
+ q = -q;
+ }
+ if (p < 0) {
+ iPtr->y = (int)(- ((-p + q/2)/q));
+ } else {
+ iPtr->y = (int)((p + q/2)/q);
+ }
+ return 0;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * Draw3DPolygon --
+ *
+ * Draw a border with 3-D appearance around the edge of a given polygon.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information is drawn in "drawable" in the form of a 3-D border
+ * borderWidth units width wide on the left of the trajectory given by
+ * pointPtr and n (or -borderWidth units wide on the right side,
+ * if borderWidth is negative).
+ *
+ *--------------------------------------------------------------
+ */
+
+static void
+Draw3DPolygon(
+ Tk_Window tkwin, /* Window for which border was
+ allocated. */
+ Drawable drawable, /* X window or pixmap in which to
+ * draw. */
+ Tk_3DBorder border, /* Token for border to draw. */
+ XPoint *points, /* Array of points describing polygon.
+ * All points must be absolute
+ * (CoordModeOrigin). */
+ int n, /* Number of points at *points. */
+ int borderWidth, /* Width of border, measured in
+ * pixels to the left of the polygon's
+ * trajectory. May be negative. */
+ int leftRelief) /* TK_RELIEF_RAISED or
+ * TK_RELIEF_SUNKEN: indicates how
+ * stuff to left of trajectory looks
+ * relative to stuff on right. */
+{
+ XPoint poly[4], b1, b2, newB1, newB2;
+ XPoint perp, c, shift1, shift2; /* Used for handling parallel lines. */
+ XPoint *p, *q;
+ GC gc;
+ int i, lightOnLeft, dx, dy, parallel, pointsSeen;
+
+ /* Handle grooves and ridges with recursive calls. */
+ if ((leftRelief == TK_RELIEF_GROOVE) || (leftRelief == TK_RELIEF_RIDGE)) {
+ int halfWidth, relief;
+
+ halfWidth = borderWidth / 2;
+ relief = (leftRelief == TK_RELIEF_GROOVE)
+ ? TK_RELIEF_RAISED : TK_RELIEF_SUNKEN;
+ Draw3DPolygon(tkwin, drawable, border, points, n, halfWidth, relief);
+ Draw3DPolygon(tkwin, drawable, border, points, n, -halfWidth, relief);
+ return;
+ }
+ /*
+ * If the polygon is already closed, drop the last point from it
+ * (we'll close it automatically).
+ */
+ p = points + (n-1);
+ q = points;
+ if ((p->x == q->x) && (p->y == q->y)) {
+ n--;
+ }
+
+ /*
+ * The loop below is executed once for each vertex in the polgon.
+ * At the beginning of each iteration things look like this:
+ *
+ * poly[1] /
+ * * /
+ * | /
+ * b1 * poly[0] (points[i-1])
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * | | *p *q
+ * b2 *--------------------*
+ * |
+ * |
+ * x-------------------------
+ *
+ * The job of this iteration is to do the following:
+ * (a) Compute x (the border corner corresponding to
+ * points[i]) and put it in poly[2]. As part of
+ * this, compute a new b1 and b2 value for the next
+ * side of the polygon.
+ * (b) Put points[i] into poly[3].
+ * (c) Draw the polygon given by poly[0..3].
+ * (d) Advance poly[0], poly[1], b1, and b2 for the
+ * next side of the polygon.
+ */
+
+ /*
+ * The above situation doesn't first come into existence until two points
+ * have been processed; the first two points are used to "prime the pump",
+ * so some parts of the processing are ommitted for these points. The
+ * variable "pointsSeen" keeps track of the priming process; it has to be
+ * separate from i in order to be able to ignore duplicate points in the
+ * polygon.
+ */
+ pointsSeen = 0;
+ for (i = -2, p = points + (n-2), q = p+1; i < n; i++, p = q, q++) {
+ if ((i == -1) || (i == n-1)) {
+ q = points;
+ }
+ if ((q->x == p->x) && (q->y == p->y)) {
+ /*
+ * Ignore duplicate points (they'd cause core dumps in
+ * ShiftLine calls below).
+ */
+ continue;
+ }
+ ShiftLine(p, q, borderWidth, &newB1);
+ newB2.x = newB1.x + (q->x - p->x);
+ newB2.y = newB1.y + (q->y - p->y);
+ poly[3] = *p;
+ parallel = 0;
+ if (pointsSeen >= 1) {
+ parallel = Intersect(&newB1, &newB2, &b1, &b2, &poly[2]);
+
+ /*
+ * If two consecutive segments of the polygon are parallel,
+ * then things get more complex. Consider the following
+ * diagram:
+ *
+ * poly[1]
+ * *----b1-----------b2------a
+ * \
+ * \
+ * *---------*----------* b
+ * poly[0] *q *p /
+ * /
+ * --*--------*----c
+ * newB1 newB2
+ *
+ * Instead of using x and *p for poly[2] and poly[3], as
+ * in the original diagram, use a and b as above. Then instead
+ * of using x and *p for the new poly[0] and poly[1], use
+ * b and c as above.
+ *
+ * Do the computation in three stages:
+ * 1. Compute a point "perp" such that the line p-perp
+ * is perpendicular to p-q.
+ * 2. Compute the points a and c by intersecting the lines
+ * b1-b2 and newB1-newB2 with p-perp.
+ * 3. Compute b by shifting p-perp to the right and
+ * intersecting it with p-q.
+ */
+
+ if (parallel) {
+ perp.x = p->x + (q->y - p->y);
+ perp.y = p->y - (q->x - p->x);
+ Intersect(p, &perp, &b1, &b2, &poly[2]);
+ Intersect(p, &perp, &newB1, &newB2, &c);
+ ShiftLine(p, &perp, borderWidth, &shift1);
+ shift2.x = shift1.x + (perp.x - p->x);
+ shift2.y = shift1.y + (perp.y - p->y);
+ Intersect(p, q, &shift1, &shift2, &poly[3]);
+ }
+ }
+ if (pointsSeen >= 2) {
+ dx = poly[3].x - poly[0].x;
+ dy = poly[3].y - poly[0].y;
+ if (dx > 0) {
+ lightOnLeft = (dy <= dx);
+ } else {
+ lightOnLeft = (dy < dx);
+ }
+ if (lightOnLeft ^ (leftRelief == TK_RELIEF_RAISED)) {
+ gc = Tk_3DBorderGC(tkwin, border, TK_3D_LIGHT_GC);
+ } else {
+ gc = Tk_3DBorderGC(tkwin, border, TK_3D_DARK_GC);
+ }
+ XFillPolygon(Tk_Display(tkwin), drawable, gc, poly, 4, Convex,
+ CoordModeOrigin);
+ }
+ b1.x = newB1.x;
+ b1.y = newB1.y;
+ b2.x = newB2.x;
+ b2.y = newB2.y;
+ poly[0].x = poly[3].x;
+ poly[0].y = poly[3].y;
+ if (parallel) {
+ poly[1].x = c.x;
+ poly[1].y = c.y;
+ } else if (pointsSeen >= 1) {
+ poly[1].x = poly[2].x;
+ poly[1].y = poly[2].y;
+ }
+ pointsSeen++;
+ }
+}
+
+static int
+ConfigureSolidPattern(Tcl_Interp *interp, Pattern *corePtr, int objc,
+ Tcl_Obj *const *objv, unsigned int flags)
+{
+ SolidPattern *patternPtr = (SolidPattern *)corePtr;
+
+ if (Blt_ConfigureWidgetFromObj(interp, patternPtr->tkwin,
+ patternPtr->classPtr->configSpecs, objc, objv, (char *)patternPtr,
+ flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawSolidRectangle --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawSolidRectangle(Tk_Window tkwin, Drawable drawable, Pattern *corePtr,
+ int x, int y, int w, int h)
+{
+ SolidPattern *patternPtr = (SolidPattern *)corePtr;
+
+ if ((h <= 0) || (w <= 0)) {
+ return;
+ }
+ if (patternPtr->alpha == 0xFF) {
+ Tk_Fill3DRectangle(tkwin, drawable, patternPtr->border, x, y, w, h,
+ 0, TK_RELIEF_FLAT);
+ } else if (patternPtr->alpha != 0x00) {
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawSolidRectangle --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawSolidPolygon(Tk_Window tkwin, Drawable drawable, Pattern *corePtr, int n,
+ XPoint *points)
+{
+ SolidPattern *patternPtr = (SolidPattern *)corePtr;
+
+ if (n < 3) {
+ return; /* Not enough points for polygon */
+ }
+ if (patternPtr->alpha == 0xFF) {
+ XFillPolygon(Tk_Display(tkwin), drawable,
+ Tk_3DBorderGC(tkwin, patternPtr->border, TK_3D_FLAT_GC),
+ points, n, Complex, CoordModeOrigin);
+ } else if (patternPtr->alpha != 0x00) {
+ }
+}
+
+static PatternClass solidPatternClass = {
+ PATTERN_SOLID,
+ solidConfigSpecs,
+ NULL, /* DestroySolidPattern */
+ ConfigureSolidPattern,
+ DrawSolidRectangle,
+ DrawSolidPolygon
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateSolidPattern --
+ *
+ * Creates a new solid background pattern.
+ *
+ * Results:
+ * Returns pointer to the new background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Pattern *
+CreateSolidPattern(void)
+{
+ SolidPattern *patternPtr;
+
+ patternPtr = calloc(1, sizeof(SolidPattern));
+ if (patternPtr == NULL) {
+ return NULL;
+ }
+ patternPtr->classPtr = &solidPatternClass;
+ patternPtr->alpha = 0xFF;
+ return (Pattern *)patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawTileRectangle --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawTileRectangle(Tk_Window tkwin, Drawable drawable, Pattern *corePtr,
+ int x, int y, int w, int h)
+{
+ TilePattern *patternPtr = (TilePattern *)corePtr;
+ //Tk_Window refWindow;
+
+ if ((h <= 0) || (w <= 0)) {
+ return;
+ }
+ if (patternPtr->tkImage == NULL) {
+ /* No image so draw solid color background using border. */
+ Tk_Fill3DRectangle(tkwin, drawable, patternPtr->border, x, y, w, h,
+ 0, TK_RELIEF_FLAT);
+ return;
+ }
+}
+
+static int
+ConfigureTilePattern(Tcl_Interp *interp, Pattern *corePtr, int objc,
+ Tcl_Obj *const *objv, unsigned int flags)
+{
+ TilePattern *patternPtr = (TilePattern *)corePtr;
+
+ if (Blt_ConfigureWidgetFromObj(interp, patternPtr->tkwin,
+ patternPtr->classPtr->configSpecs, objc, objv, (char *)patternPtr,
+ flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static PatternClass tilePatternClass = {
+ PATTERN_TILE,
+ tileConfigSpecs,
+ NULL, /* DestroyTilePattern, */
+ ConfigureTilePattern,
+ DrawTileRectangle,
+ DrawSolidPolygon
+
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateTilePattern --
+ *
+ * Creates a new image background pattern.
+ *
+ * Results:
+ * Returns pointer to the new background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Pattern *
+CreateTilePattern(void)
+{
+ TilePattern *patternPtr;
+
+ patternPtr = calloc(1, sizeof(TilePattern));
+ if (patternPtr == NULL) {
+ return NULL;
+ }
+ patternPtr->classPtr = &tilePatternClass;
+ patternPtr->reference = REFERENCE_TOPLEVEL;
+ return (Pattern *)patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawGradientRectangle --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawGradientRectangle(Tk_Window tkwin, Drawable drawable, Pattern *corePtr,
+ int x, int y, int w, int h)
+{
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawGradientPolygon --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawGradientPolygon(Tk_Window tkwin, Drawable drawable, Pattern *corePtr,
+ int n, XPoint *points)
+{
+ GradientPattern *patternPtr = (GradientPattern *)corePtr;
+ Tk_Window refWindow;
+
+ if (patternPtr->reference == REFERENCE_SELF) {
+ refWindow = tkwin;
+ } else if (patternPtr->reference == REFERENCE_TOPLEVEL) {
+ refWindow = Blt_Toplevel(tkwin);
+ } else if (patternPtr->reference == REFERENCE_WINDOW) {
+ refWindow = patternPtr->refWindow;
+ } else if (patternPtr->reference == REFERENCE_NONE) {
+ refWindow = NULL;
+ } else {
+ return; /* Unknown reference window. */
+ }
+ if (n < 3) {
+ return; /* Not enough points for polygon */
+ }
+ if (patternPtr->alpha == 0xFF) {
+ XFillPolygon(Tk_Display(tkwin), drawable,
+ Tk_3DBorderGC(tkwin, patternPtr->border, TK_3D_FLAT_GC),
+ points, n, Complex, CoordModeOrigin);
+ } else if (patternPtr->alpha != 0x00) {
+ }
+}
+
+static int
+ConfigureGradientPattern(Tcl_Interp *interp, Pattern *corePtr, int objc,
+ Tcl_Obj *const *objv, unsigned int flags)
+{
+ GradientPattern *patternPtr = (GradientPattern *)corePtr;
+
+ if (Blt_ConfigureWidgetFromObj(interp, patternPtr->tkwin,
+ patternPtr->classPtr->configSpecs,
+ objc, objv, (char *)patternPtr,
+ flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (patternPtr->alpha != 0xFF) {
+ }
+ return TCL_OK;
+}
+
+
+static PatternClass gradientPatternClass = {
+ PATTERN_GRADIENT,
+ gradientConfigSpecs,
+ NULL, /* DestroyGradientPattern, */
+ ConfigureGradientPattern,
+ DrawGradientRectangle,
+ DrawGradientPolygon,
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateGradientPattern --
+ *
+ * Creates a new solid background pattern.
+ *
+ * Results:
+ * Returns pointer to the new background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Pattern *
+CreateGradientPattern(void)
+{
+ GradientPattern *patternPtr;
+
+ patternPtr = calloc(1, sizeof(GradientPattern));
+ if (patternPtr == NULL) {
+ return NULL;
+ }
+ patternPtr->classPtr = &gradientPatternClass;
+ patternPtr->reference = REFERENCE_TOPLEVEL;
+ // patternPtr->gradient.shape = BLT_GRADIENT_SHAPE_LINEAR;
+ // patternPtr->gradient.path = BLT_GRADIENT_PATH_Y;
+ // patternPtr->gradient.jitter = FALSE;
+ //patternPtr->gradient.logScale = TRUE;
+ patternPtr->alpha = 255;
+ return (Pattern *)patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawTextureRectangle --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawTextureRectangle(Tk_Window tkwin, Drawable drawable, Pattern *corePtr,
+ int x, int y, int w, int h)
+{
+}
+
+static int
+ConfigureTexturePattern(Tcl_Interp *interp, Pattern *corePtr, int objc,
+ Tcl_Obj *const *objv, unsigned int flags)
+{
+ TexturePattern *patternPtr = (TexturePattern *)corePtr;
+
+ if (Blt_ConfigureWidgetFromObj(interp, patternPtr->tkwin,
+ patternPtr->classPtr->configSpecs, objc, objv, (char *)patternPtr,
+ flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static PatternClass texturePatternClass = {
+ PATTERN_TEXTURE,
+ textureConfigSpecs,
+ NULL, /* DestroyTexturePattern, */
+ ConfigureTexturePattern,
+ DrawTextureRectangle,
+ DrawSolidPolygon
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateTexturePattern --
+ *
+ * Creates a new texture background pattern.
+ *
+ * Results:
+ * Returns pointer to the new background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Pattern *
+CreateTexturePattern()
+{
+ TexturePattern *patternPtr;
+
+ patternPtr = calloc(1, sizeof(TexturePattern));
+ if (patternPtr == NULL) {
+ return NULL;
+ }
+ patternPtr->classPtr = &texturePatternClass;
+ patternPtr->reference = REFERENCE_TOPLEVEL;
+ return (Pattern *)patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreatePattern --
+ *
+ * Creates a new background pattern.
+ *
+ * Results:
+ * Returns pointer to the new background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Pattern *
+CreatePattern(BackgroundInterpData *dataPtr, Tcl_Interp *interp, int type)
+{
+ Pattern *patternPtr;
+
+ switch (type) {
+ case PATTERN_SOLID:
+ patternPtr = CreateSolidPattern();
+ break;
+ case PATTERN_TILE:
+ patternPtr = CreateTilePattern();
+ break;
+ case PATTERN_GRADIENT:
+ patternPtr = CreateGradientPattern();
+ break;
+ case PATTERN_TEXTURE:
+ patternPtr = CreateTexturePattern();
+ break;
+ default:
+ abort();
+ break;
+ }
+ if (patternPtr == NULL) {
+ Tcl_AppendResult(interp, "can't allocate background pattern",
+ (char *)NULL);
+ return NULL;
+ }
+ patternPtr->dataPtr = dataPtr;
+ Blt_InitHashTable(&patternPtr->pictTable, BLT_ONE_WORD_KEYS);
+ patternPtr->chain = Blt_Chain_Create();
+ patternPtr->tkwin = Tk_MainWindow(interp);
+ patternPtr->display = Tk_Display(patternPtr->tkwin);
+ return patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyPattern --
+ *
+ * Removes the client from the servers's list of clients and memory used
+ * by the client token is released. When the last client is deleted, the
+ * server is also removed.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DestroyPattern(Pattern *patternPtr)
+{
+ Blt_FreeOptions(patternPtr->classPtr->configSpecs, (char *)patternPtr,
+ patternPtr->display, 0);
+ if (patternPtr->classPtr->destroyProc != NULL) {
+ (*patternPtr->classPtr->destroyProc)(patternPtr);
+ }
+ if (patternPtr->border != NULL) {
+ Tk_Free3DBorder(patternPtr->border);
+ }
+ if (patternPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&patternPtr->dataPtr->patternTable,
+ patternPtr->hashPtr);
+ }
+ // ClearCache(patternPtr);
+ Blt_Chain_Destroy(patternPtr->chain);
+ Blt_DeleteHashTable(&patternPtr->pictTable);
+ free(patternPtr);
+ patternPtr = NULL;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyBackground --
+ *
+ * Removes the client from the servers's list of clients and memory used
+ * by the client token is released. When the last client is deleted, the
+ * server is also removed.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DestroyBackground(Background *bgPtr)
+{
+ Pattern *patternPtr = bgPtr->corePtr;
+
+ Blt_Chain_DeleteLink(patternPtr->chain, bgPtr->link);
+ if (Blt_Chain_GetLength(patternPtr->chain) <= 0) {
+ DestroyPattern(patternPtr);
+ }
+ free(bgPtr);
+ bgPtr = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetBackgroundInterpData --
+ *
+ *---------------------------------------------------------------------------
+ */
+static BackgroundInterpData *
+GetBackgroundInterpData(Tcl_Interp *interp)
+{
+ BackgroundInterpData *dataPtr;
+ Tcl_InterpDeleteProc *proc;
+
+ dataPtr = (BackgroundInterpData *)
+ Tcl_GetAssocData(interp, BG_PATTERN_THREAD_KEY, &proc);
+ if (dataPtr == NULL) {
+ dataPtr = malloc(sizeof(BackgroundInterpData));
+ dataPtr->interp = interp;
+ dataPtr->nextId = 1;
+
+
+ /* FIXME: Create interp delete proc to teardown the hash table and
+ * data entry. Must occur after all the widgets have been destroyed
+ * (clients of the background pattern). */
+
+ Tcl_SetAssocData(interp, BG_PATTERN_THREAD_KEY,
+ (Tcl_InterpDeleteProc *)NULL, dataPtr);
+ Blt_InitHashTable(&dataPtr->patternTable, BLT_STRING_KEYS);
+ }
+ return dataPtr;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetBackground
+ *
+ * Creates a new background from the given pattern description. The
+ * background structure returned is a token for the client to use the
+ * background. If the pattern isn't a solid pattern (i.e. a solid color
+ * that Tk_Get3DBorder will accept) then the pattern must already exist.
+ * Solid patterns are the exception to this rule. This lets "-background
+ * #ffffff" work without already having allocated a background pattern
+ * "#ffffff".
+ *
+ * Results:
+ * Returns a background pattern token.
+ *
+ * Side Effects:
+ * Memory is allocated for the new token.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_Background
+Blt_GetBackground(Tcl_Interp *interp, Tk_Window tkwin, const char *name)
+{
+ Pattern *patternPtr;
+ BackgroundInterpData *dataPtr;
+ Background *bgPtr; /* Pattern container. */
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ /* Create new token for the background. */
+ bgPtr = calloc(1, sizeof(Background));
+ if (bgPtr == NULL) {
+ Tcl_AppendResult(interp, "can't allocate background \"", name, "\".",
+ (char *)NULL);
+ return NULL;
+ }
+ dataPtr = GetBackgroundInterpData(interp);
+ hPtr = Blt_CreateHashEntry(&dataPtr->patternTable, name, &isNew);
+ if (isNew) {
+ Tk_3DBorder border;
+
+ /* Pattern doesn't already exist, see if it's a color name
+ * (i.e. something that Tk_Get3DBorder will accept). */
+ border = Tk_Get3DBorder(interp, tkwin, name);
+ if (border == NULL) {
+ goto error; /* Nope. It's an error. */
+ }
+ patternPtr = CreatePattern(dataPtr, interp, PATTERN_SOLID);
+ if (patternPtr == NULL) {
+ Tk_Free3DBorder(border);
+ goto error; /* Can't allocate new pattern. */
+ }
+ patternPtr->border = border;
+ patternPtr->hashPtr = hPtr;
+ patternPtr->name = Blt_GetHashKey(&dataPtr->patternTable, hPtr);
+ patternPtr->link = NULL;
+ Blt_SetHashValue(hPtr, patternPtr);
+ } else {
+ patternPtr = Blt_GetHashValue(hPtr);
+ assert(patternPtr != NULL);
+ }
+ /* Add the new background to the pattern's list of clients. */
+ bgPtr->link = Blt_Chain_Append(patternPtr->chain, bgPtr);
+ bgPtr->corePtr = patternPtr;
+ return bgPtr;
+ error:
+ free(bgPtr);
+ Blt_DeleteHashEntry(&dataPtr->patternTable, hPtr);
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetBackgroundFromObj
+ *
+ * Retrieves a new token of a background pattern from the named background
+ * pattern.
+ *
+ * Results:
+ * Returns a background pattern token.
+ *
+ * Side Effects:
+ * Memory is allocated for the new token.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_Background
+Blt_GetBackgroundFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ return Blt_GetBackground(interp, tkwin, Tcl_GetString(objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_SetBackgroundChangedProc
+ *
+ * Sets the routine to called when an image changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The designated routine will be called the next time the image
+ * associated with the tile changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_SetBackgroundChangedProc(
+ Background *bgPtr, /* Background to register callback
+ * with. */
+ Blt_BackgroundChangedProc *notifyProc, /* Function to call when pattern
+ * has changed. NULL indicates to
+ * unset the callback.*/
+ ClientData clientData)
+{
+ bgPtr->notifyProc = notifyProc;
+ bgPtr->clientData = clientData;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeBackground
+ *
+ * Removes the background pattern token.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Memory is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FreeBackground(Background *bgPtr)
+{
+ Pattern *patternPtr = bgPtr->corePtr;
+
+ assert(patternPtr != NULL);
+ DestroyBackground(bgPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetBackgroundOrigin
+ *
+ * Returns the coordinates of the origin of the background pattern
+ * referenced by the token.
+ *
+ * Results:
+ * Returns the coordinates of the origin.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_GetBackgroundOrigin(Background *bgPtr, int *xPtr, int *yPtr)
+{
+ *xPtr = bgPtr->corePtr->xOrigin;
+ *yPtr = bgPtr->corePtr->yOrigin;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_SetBackgroundOrigin
+ *
+ * Sets the origin of the background pattern referenced by the token.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_SetBackgroundOrigin(Tk_Window tkwin, Background *bgPtr, int x, int y)
+{
+ Pattern *patternPtr = bgPtr->corePtr;
+ patternPtr->xOrigin = x;
+ patternPtr->yOrigin = y;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NameOfBackground
+ *
+ * Returns the name of the core background pattern referenced by the
+ * token.
+ *
+ * Results:
+ * Return the name of the background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_NameOfBackground(Background *bgPtr)
+{
+ if (bgPtr->corePtr->name == NULL) {
+ return "";
+ }
+ return bgPtr->corePtr->name;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_BackgroundBorderColor
+ *
+ * Returns the border color of the background pattern referenced by the
+ * token.
+ *
+ * Results:
+ * Returns the XColor representing the border color of the pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+XColor *
+Blt_BackgroundBorderColor(Background *bgPtr)
+{
+ return Tk_3DBorderColor(bgPtr->corePtr->border);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_BackgroundBorder
+ *
+ * Returns the border of the background pattern referenced by the token.
+ *
+ * Results:
+ * Return the border of the background pattern.
+ *
+ *---------------------------------------------------------------------------
+ */
+Tk_3DBorder
+Blt_BackgroundBorder(Background *bgPtr)
+{
+ return bgPtr->corePtr->border;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawBackgroundRectangle
+ *
+ * Draws the background pattern in the designated window.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawBackgroundRectangle(Tk_Window tkwin, Drawable drawable,
+ Background *bgPtr, int x, int y, int w, int h,
+ int borderWidth, int relief)
+{
+ Tk_Draw3DRectangle(tkwin, drawable, bgPtr->corePtr->border, x, y, w, h,
+ borderWidth, relief);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FillBackgroundRectangle
+ *
+ * Draws the background pattern in the designated window.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FillBackgroundRectangle(Tk_Window tkwin, Drawable drawable,
+ Background *bgPtr, int x, int y, int w, int h,
+ int borderWidth, int relief)
+{
+ Pattern *patternPtr;
+
+ if ((h < 1) || (w < 1)) {
+ return;
+ }
+ patternPtr = bgPtr->corePtr;
+ (*patternPtr->classPtr->drawRectangleProc)(tkwin, drawable, patternPtr,
+ x, y, w, h);
+ if ((relief != TK_RELIEF_FLAT) && (borderWidth > 0)) {
+ Tk_Draw3DRectangle(tkwin, drawable, patternPtr->border, x, y, w, h,
+ borderWidth, relief);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FillBackgroundPolygon
+ *
+ * Draws the background pattern in the designated window.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FillBackgroundPolygon(Tk_Window tkwin, Drawable drawable, Background *bgPtr,
+ XPoint *points, int n, int borderWidth, int relief)
+{
+ Pattern *patternPtr;
+
+ if (n < 3) {
+ return;
+ }
+ patternPtr = bgPtr->corePtr;
+ (*patternPtr->classPtr->drawPolygonProc)(tkwin, drawable, patternPtr,
+ n, points);
+ if ((relief != TK_RELIEF_FLAT) && (borderWidth != 0)) {
+ Draw3DPolygon(tkwin, drawable, patternPtr->border, points, n,
+ borderWidth, relief);
+ }
+}
+
+void
+Blt_SetBackgroundClipRegion(Tk_Window tkwin, Background *bgPtr, TkRegion rgn)
+{
+ Display *display;
+ GC gc;
+
+ display = Tk_Display(tkwin);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_LIGHT_GC);
+ TkSetRegion(display, gc, rgn);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_DARK_GC);
+ TkSetRegion(display, gc, rgn);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_FLAT_GC);
+ TkSetRegion(display, gc, rgn);
+}
+
+
+void
+Blt_UnsetBackgroundClipRegion(Tk_Window tkwin, Background *bgPtr)
+{
+ Display *display;
+ GC gc;
+
+ display = Tk_Display(tkwin);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_LIGHT_GC);
+ XSetClipMask(display, gc, None);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_DARK_GC);
+ XSetClipMask(display, gc, None);
+ gc = Tk_3DBorderGC(tkwin, bgPtr->corePtr->border, TK_3D_FLAT_GC);
+ XSetClipMask(display, gc, None);
+}
diff --git a/tlt3.0/bltBgStyle.h b/tlt3.0/bltBgStyle.h
new file mode 100644
index 0000000..5ddbbab
--- /dev/null
+++ b/tlt3.0/bltBgStyle.h
@@ -0,0 +1,74 @@
+
+/*
+ * bltBgPattern.h --
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_BGPATTERN_H
+#define _BLT_BGPATTERN_H
+
+typedef struct _Blt_Background *Blt_Background;
+
+typedef void Blt_BackgroundChangedProc(ClientData clientData);
+
+extern Blt_Background Blt_GetBackground(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *styleName);
+
+extern Blt_Background Blt_GetBackgroundFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr);
+
+extern XColor *Blt_BackgroundBorderColor(Blt_Background bg);
+
+extern Tk_3DBorder Blt_BackgroundBorder(Blt_Background bg);
+
+extern const char *Blt_NameOfBackground(Blt_Background bg);
+
+extern void Blt_FreeBackground(Blt_Background bg);
+
+extern void Blt_DrawBackgroundRectangle(Tk_Window tkwin, Drawable drawable,
+ Blt_Background bg, int x, int y, int width, int height, int borderWidth,
+ int relief);
+
+extern void Blt_FillBackgroundRectangle(Tk_Window tkwin, Drawable drawable,
+ Blt_Background bg, int x, int y, int width, int height,
+ int borderWidth, int relief);
+
+extern void Blt_FillBackgroundPolygon(Tk_Window tkwin, Drawable drawable,
+ Blt_Background bg, XPoint *points, int nPoints, int borderWidth,
+ int leftRelief);
+
+extern void Blt_GetBackgroundOrigin(Blt_Background bg, int *xPtr,int *yPtr);
+
+extern void Blt_SetBackgroundChangedProc(Blt_Background bg,
+ Blt_BackgroundChangedProc *notifyProc, ClientData clientData);
+
+extern void Blt_SetBackgroundOrigin(Tk_Window tkwin, Blt_Background bg,
+ int x, int y);
+
+extern void Blt_UnsetBackgroundClipRegion(Tk_Window tkwin,
+ Blt_Background bg);
+
+extern void Blt_SetBackgroundClipRegion(Tk_Window tkwin, Blt_Background bg,
+ TkRegion rgn);
+
+#endif /* BLT_BGPATTERN_H */
diff --git a/tlt3.0/bltBind.c b/tlt3.0/bltBind.c
new file mode 100644
index 0000000..e9bd3f8
--- /dev/null
+++ b/tlt3.0/bltBind.c
@@ -0,0 +1,776 @@
+
+/*
+ * bltBind.c --
+ *
+ * This module implements object binding procedures for the BLT toolkit.
+ *
+ * Copyright 1998 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+#include "bltBind.h"
+
+static Tk_EventProc BindProc;
+
+typedef struct _Blt_BindTable BindTable;
+
+/*
+ * Binding table procedures.
+ */
+#define REPICK_IN_PROGRESS (1<<0)
+#define LEFT_GRABBED_ITEM (1<<1)
+
+#define ALL_BUTTONS_MASK \
+ (Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask)
+
+#ifndef VirtualEventMask
+#define VirtualEventMask (1L << 30)
+#endif
+
+#define ALL_VALID_EVENTS_MASK \
+ (ButtonMotionMask | Button1MotionMask | Button2MotionMask | \
+ Button3MotionMask | Button4MotionMask | Button5MotionMask | \
+ ButtonPressMask | ButtonReleaseMask | EnterWindowMask | \
+ LeaveWindowMask | KeyPressMask | KeyReleaseMask | \
+ PointerMotionMask | VirtualEventMask)
+
+static int buttonMasks[] =
+{
+ 0, /* No buttons pressed */
+ Button1Mask, Button2Mask, Button3Mask, Button4Mask, Button5Mask,
+};
+
+
+/*
+ * How to make drag&drop work?
+ *
+ * Right now we generate pseudo <Enter> <Leave> events within button grab
+ * on an object. They're marked NotifyVirtual instead of NotifyAncestor.
+ * A better solution: generate new-style virtual <<DragEnter>>
+ * <<DragMotion>> <<DragLeave>> events. These virtual events don't have
+ * to exist as "real" event sequences, like virtual events do now.
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DoEvent --
+ *
+ * This procedure is called to invoke binding processing for a new event
+ * that is associated with the current item for a legend.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the bindings for the legend. A binding script could delete
+ * an entry, so callers should protect themselves with Tcl_Preserve and
+ * Tcl_Release.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DoEvent(
+ BindTable *bindPtr, /* Binding information for widget in which
+ * event occurred. */
+ XEvent *eventPtr, /* Real or simulated X event that is to be
+ * processed. */
+ ClientData item, /* Item picked. */
+ ClientData context) /* Context of item. */
+{
+ Blt_List tagList;
+
+ if ((bindPtr->tkwin == NULL) || (bindPtr->bindingTable == NULL)) {
+ return;
+ }
+ if ((eventPtr->type == KeyPress) || (eventPtr->type == KeyRelease)) {
+ item = bindPtr->focusItem;
+ context = bindPtr->focusContext;
+ }
+ if (item == NULL) {
+ return;
+ }
+ /*
+ * Invoke the binding system.
+ */
+ tagList = Blt_List_Create(BLT_ONE_WORD_KEYS);
+ if (bindPtr->tagProc == NULL) {
+ Blt_List_Append(tagList, Tk_GetUid("all"), 0);
+ Blt_List_Append(tagList, (char *)item, 0);
+ } else {
+ (*bindPtr->tagProc) (bindPtr, item, context, tagList);
+ }
+ if (Blt_List_GetLength(tagList) > 0) {
+ int nTags;
+ ClientData *tagArray;
+#define MAX_STATIC_TAGS 64
+ ClientData staticTags[MAX_STATIC_TAGS];
+ Blt_ListNode node;
+
+ tagArray = staticTags;
+ nTags = Blt_List_GetLength(tagList);
+ if (nTags >= MAX_STATIC_TAGS) {
+ tagArray = malloc(sizeof(ClientData) * nTags);
+
+ }
+ nTags = 0;
+ for (node = Blt_List_FirstNode(tagList); node != NULL;
+ node = Blt_List_NextNode(node)) {
+ tagArray[nTags++] = (ClientData)Blt_List_GetKey(node);
+ }
+ Tk_BindEvent(bindPtr->bindingTable, eventPtr, bindPtr->tkwin, nTags,
+ tagArray);
+ if (tagArray != staticTags) {
+ free(tagArray);
+ }
+ }
+ Blt_List_Destroy(tagList);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PickCurrentItem --
+ *
+ * Find the topmost item in a legend that contains a given location and
+ * mark the the current item. If the current item has changed, generate
+ * a fake exit event on the old current item and a fake enter event on
+ * the new current item.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The current item may change. If it does, then the commands associated
+ * with item entry and exit could do just about anything. A binding
+ * script could delete the legend, so callers should protect themselves
+ * with Tcl_Preserve and Tcl_Release.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+PickCurrentItem(
+ BindTable *bindPtr, /* Binding table information. */
+ XEvent *eventPtr) /* Event describing location of mouse cursor.
+ * Must be EnterWindow, LeaveWindow,
+ * ButtonRelease, or MotionNotify. */
+{
+ int buttonDown;
+ ClientData newItem, oldItem;
+ ClientData newContext;
+
+ /*
+ * Check whether or not a button is down. If so, we'll log entry and exit
+ * into and out of the current item, but not entry into any other item.
+ * This implements a form of grabbing equivalent to what the X server does
+ * for windows.
+ */
+ buttonDown = (bindPtr->state & ALL_BUTTONS_MASK);
+ if (!buttonDown) {
+ bindPtr->flags &= ~LEFT_GRABBED_ITEM;
+ }
+
+ /*
+ * Save information about this event in the widget. The event in the
+ * widget is used for two purposes:
+ *
+ * 1. Event bindings: if the current item changes, fake events are
+ * generated to allow item-enter and item-leave bindings to trigger.
+ * 2. Reselection: if the current item gets deleted, can use the
+ * saved event to find a new current item.
+ * Translate MotionNotify events into EnterNotify events, since that's
+ * what gets reported to item handlers.
+ */
+
+ if (eventPtr != &bindPtr->pickEvent) {
+ if ((eventPtr->type == MotionNotify) ||
+ (eventPtr->type == ButtonRelease)) {
+ bindPtr->pickEvent.xcrossing.type = EnterNotify;
+ bindPtr->pickEvent.xcrossing.serial = eventPtr->xmotion.serial;
+ bindPtr->pickEvent.xcrossing.send_event =
+ eventPtr->xmotion.send_event;
+ bindPtr->pickEvent.xcrossing.display = eventPtr->xmotion.display;
+ bindPtr->pickEvent.xcrossing.window = eventPtr->xmotion.window;
+ bindPtr->pickEvent.xcrossing.root = eventPtr->xmotion.root;
+ bindPtr->pickEvent.xcrossing.subwindow = None;
+ bindPtr->pickEvent.xcrossing.time = eventPtr->xmotion.time;
+ bindPtr->pickEvent.xcrossing.x = eventPtr->xmotion.x;
+ bindPtr->pickEvent.xcrossing.y = eventPtr->xmotion.y;
+ bindPtr->pickEvent.xcrossing.x_root = eventPtr->xmotion.x_root;
+ bindPtr->pickEvent.xcrossing.y_root = eventPtr->xmotion.y_root;
+ bindPtr->pickEvent.xcrossing.mode = NotifyNormal;
+ bindPtr->pickEvent.xcrossing.detail = NotifyNonlinear;
+ bindPtr->pickEvent.xcrossing.same_screen
+ = eventPtr->xmotion.same_screen;
+ bindPtr->pickEvent.xcrossing.focus = False;
+ bindPtr->pickEvent.xcrossing.state = eventPtr->xmotion.state;
+ } else {
+ bindPtr->pickEvent = *eventPtr;
+ }
+ }
+ bindPtr->activePick = TRUE;
+
+ /*
+ * If this is a recursive call (there's already a partially completed call
+ * pending on the stack; it's in the middle of processing a Leave event
+ * handler for the old current item) then just return; the pending call
+ * will do everything that's needed.
+ */
+ if (bindPtr->flags & REPICK_IN_PROGRESS) {
+ return;
+ }
+ /*
+ * A LeaveNotify event automatically means that there's no current item,
+ * so the check for closest item can be skipped.
+ */
+ newContext = NULL;
+ if (bindPtr->pickEvent.type != LeaveNotify) {
+ int x, y;
+
+ x = bindPtr->pickEvent.xcrossing.x;
+ y = bindPtr->pickEvent.xcrossing.y;
+ newItem = (*bindPtr->pickProc) (bindPtr->clientData, x, y, &newContext);
+ } else {
+ newItem = NULL;
+ }
+ if (((newItem == bindPtr->currentItem) &&
+ (newContext == bindPtr->currentContext)) &&
+ ((bindPtr->flags & LEFT_GRABBED_ITEM) == 0)) {
+ /*
+ * Nothing to do: the current item hasn't changed.
+ */
+ return;
+ }
+ /*
+ * Simulate a LeaveNotify event on the previous current item and an
+ * EnterNotify event on the new current item. Remove the "current" tag
+ * from the previous current item and place it on the new current item.
+ */
+ oldItem = bindPtr->currentItem;
+ Tcl_Preserve(oldItem);
+ Tcl_Preserve(newItem);
+
+ if ((bindPtr->currentItem != NULL) &&
+ ((newItem != bindPtr->currentItem) ||
+ (newContext != bindPtr->currentContext)) &&
+ ((bindPtr->flags & LEFT_GRABBED_ITEM) == 0)) {
+ XEvent event;
+
+ event = bindPtr->pickEvent;
+ event.type = LeaveNotify;
+ /*
+ * If the event's detail happens to be NotifyInferior the binding
+ * mechanism will discard the event. To be consistent, always use
+ * NotifyAncestor.
+ */
+ event.xcrossing.detail = NotifyAncestor;
+
+ bindPtr->flags |= REPICK_IN_PROGRESS;
+ DoEvent(bindPtr, &event, bindPtr->currentItem, bindPtr->currentContext);
+ bindPtr->flags &= ~REPICK_IN_PROGRESS;
+
+ /*
+ * Note: during DoEvent above, it's possible that bindPtr->newItem got
+ * reset to NULL because the item was deleted.
+ */
+ }
+ if (((newItem != bindPtr->currentItem) ||
+ (newContext != bindPtr->currentContext)) &&
+ (buttonDown)) {
+ XEvent event;
+
+ bindPtr->flags |= LEFT_GRABBED_ITEM;
+ event = bindPtr->pickEvent;
+ if ((newItem != bindPtr->newItem) ||
+ (newContext != bindPtr->newContext)) {
+ ClientData savedItem;
+ ClientData savedContext;
+
+ /*
+ * Generate <Enter> and <Leave> events for objects during button
+ * grabs. This isn't standard. But for example, it allows one to
+ * provide balloon help on the individual entries of the Hierbox
+ * widget.
+ */
+ savedItem = bindPtr->currentItem;
+ savedContext = bindPtr->currentContext;
+ if (bindPtr->newItem != NULL) {
+ event.type = LeaveNotify;
+ event.xcrossing.detail = NotifyVirtual /* Ancestor */ ;
+ bindPtr->currentItem = bindPtr->newItem;
+ DoEvent(bindPtr, &event, bindPtr->newItem, bindPtr->newContext);
+ }
+ bindPtr->newItem = newItem;
+ bindPtr->newContext = newContext;
+ if (newItem != NULL) {
+ event.type = EnterNotify;
+ event.xcrossing.detail = NotifyVirtual /* Ancestor */ ;
+ bindPtr->currentItem = newItem;
+ DoEvent(bindPtr, &event, newItem, newContext);
+ }
+ bindPtr->currentItem = savedItem;
+ bindPtr->currentContext = savedContext;
+ }
+ goto done;
+ }
+ /*
+ * Special note: it's possible that
+ * bindPtr->newItem == bindPtr->currentItem
+ * here. This can happen, for example, if LEFT_GRABBED_ITEM was set.
+ */
+
+ bindPtr->flags &= ~LEFT_GRABBED_ITEM;
+ bindPtr->currentItem = bindPtr->newItem = newItem;
+ bindPtr->currentContext = bindPtr->newContext = newContext;
+ if (bindPtr->currentItem != NULL) {
+ XEvent event;
+
+ event = bindPtr->pickEvent;
+ event.type = EnterNotify;
+ event.xcrossing.detail = NotifyAncestor;
+ DoEvent(bindPtr, &event, newItem, newContext);
+ }
+ done:
+ Tcl_Release(newItem);
+ Tcl_Release(oldItem);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BindProc --
+ *
+ * This procedure is invoked by the Tk dispatcher to handle events
+ * associated with bindings on items.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Depends on the command invoked as part of the binding
+ * (if there was any).
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+BindProc(
+ ClientData clientData, /* Pointer to widget structure. */
+ XEvent *eventPtr) /* Pointer to X event that just happened. */
+{
+ BindTable *bindPtr = clientData;
+ int mask;
+
+ Tcl_Preserve(bindPtr->clientData);
+ /*
+ * This code below keeps track of the current modifier state in
+ * bindPtr->state. This information is used to defer repicks of the
+ * current item while buttons are down.
+ */
+ switch (eventPtr->type) {
+ case ButtonPress:
+ case ButtonRelease:
+ mask = 0;
+ if ((eventPtr->xbutton.button >= Button1) &&
+ (eventPtr->xbutton.button <= Button5)) {
+ mask = buttonMasks[eventPtr->xbutton.button];
+ }
+ /*
+ * For button press events, repick the current item using the button
+ * state before the event, then process the event. For button release
+ * events, first process the event, then repick the current item using
+ * the button state *after* the event (the button has logically gone
+ * up before we change the current item).
+ */
+ if (eventPtr->type == ButtonPress) {
+
+ /*
+ * On a button press, first repick the current item using the
+ * button state before the event, the process the event.
+ */
+
+ bindPtr->state = eventPtr->xbutton.state;
+ PickCurrentItem(bindPtr, eventPtr);
+ bindPtr->state ^= mask;
+ DoEvent(bindPtr, eventPtr, bindPtr->currentItem,
+ bindPtr->currentContext);
+
+ } else {
+
+ /*
+ * Button release: first process the event, with the button still
+ * considered to be down. Then repick the current item under the
+ * assumption that the button is no longer down.
+ */
+ bindPtr->state = eventPtr->xbutton.state;
+ DoEvent(bindPtr, eventPtr, bindPtr->currentItem,
+ bindPtr->currentContext);
+ eventPtr->xbutton.state ^= mask;
+ bindPtr->state = eventPtr->xbutton.state;
+ PickCurrentItem(bindPtr, eventPtr);
+ eventPtr->xbutton.state ^= mask;
+ }
+ break;
+
+ case EnterNotify:
+ case LeaveNotify:
+ bindPtr->state = eventPtr->xcrossing.state;
+ PickCurrentItem(bindPtr, eventPtr);
+ break;
+
+ case MotionNotify:
+ bindPtr->state = eventPtr->xmotion.state;
+ PickCurrentItem(bindPtr, eventPtr);
+ DoEvent(bindPtr, eventPtr, bindPtr->currentItem,
+ bindPtr->currentContext);
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ bindPtr->state = eventPtr->xkey.state;
+ PickCurrentItem(bindPtr, eventPtr);
+ DoEvent(bindPtr, eventPtr, bindPtr->currentItem,
+ bindPtr->currentContext);
+ break;
+ }
+ Tcl_Release(bindPtr->clientData);
+}
+
+int
+Blt_ConfigureBindings(
+ Tcl_Interp *interp,
+ BindTable *bindPtr,
+ ClientData item,
+ int argc,
+ const char **argv)
+{
+ const char *command;
+ unsigned long mask;
+ const char *seq;
+
+ if (argc == 0) {
+ Tk_GetAllBindings(interp, bindPtr->bindingTable, item);
+ return TCL_OK;
+ }
+ if (argc == 1) {
+ command = Tk_GetBinding(interp, bindPtr->bindingTable, item, argv[0]);
+ if (command == NULL) {
+ Tcl_AppendResult(interp, "can't find event \"", argv[0], "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), command, -1);
+ return TCL_OK;
+ }
+
+ seq = argv[0];
+ command = argv[1];
+
+ if (command[0] == '\0') {
+ return Tk_DeleteBinding(interp, bindPtr->bindingTable, item, seq);
+ }
+
+ if (command[0] == '+') {
+ mask = Tk_CreateBinding(interp, bindPtr->bindingTable, item, seq,
+ command + 1, TRUE);
+ } else {
+ mask = Tk_CreateBinding(interp, bindPtr->bindingTable, item, seq,
+ command, FALSE);
+ }
+ if (mask == 0) {
+ Tcl_AppendResult(interp, "event mask can't be zero for \"", item, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (mask & (unsigned)~ALL_VALID_EVENTS_MASK) {
+ Tk_DeleteBinding(interp, bindPtr->bindingTable, item, seq);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "requested illegal events; ",
+ "only key, button, motion, enter, leave, and virtual ",
+ "events may be used", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+int
+Blt_ConfigureBindingsFromObj(
+ Tcl_Interp *interp,
+ BindTable *bindPtr,
+ ClientData item,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ const char *command;
+ unsigned long mask;
+ const char *seq;
+ const char *string;
+
+ if (objc == 0) {
+ Tk_GetAllBindings(interp, bindPtr->bindingTable, item);
+ return TCL_OK;
+ }
+ string = Tcl_GetString(objv[0]);
+ if (objc == 1) {
+ command = Tk_GetBinding(interp, bindPtr->bindingTable, item, string);
+ if (command == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "invalid binding event \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), command, -1);
+ return TCL_OK;
+ }
+
+ seq = string;
+ command = Tcl_GetString(objv[1]);
+
+ if (command[0] == '\0') {
+ return Tk_DeleteBinding(interp, bindPtr->bindingTable, item, seq);
+ }
+
+ if (command[0] == '+') {
+ mask = Tk_CreateBinding(interp, bindPtr->bindingTable, item, seq,
+ command + 1, TRUE);
+ } else {
+ mask = Tk_CreateBinding(interp, bindPtr->bindingTable, item, seq,
+ command, FALSE);
+ }
+ if (mask == 0) {
+ return TCL_ERROR;
+ }
+ if (mask & (unsigned)~ALL_VALID_EVENTS_MASK) {
+ Tk_DeleteBinding(interp, bindPtr->bindingTable, item, seq);
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "requested illegal events; ",
+ "only key, button, motion, enter, leave, and virtual ",
+ "events may be used", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+Blt_BindTable
+Blt_CreateBindingTable(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ ClientData clientData,
+ Blt_BindPickProc *pickProc,
+ Blt_BindTagProc *tagProc)
+{
+ unsigned int mask;
+ BindTable *bindPtr;
+
+ bindPtr = calloc(1, sizeof(BindTable));
+ bindPtr->bindingTable = Tk_CreateBindingTable(interp);
+ bindPtr->clientData = clientData;
+ bindPtr->tkwin = tkwin;
+ bindPtr->pickProc = pickProc;
+ bindPtr->tagProc = tagProc;
+ mask = (KeyPressMask | KeyReleaseMask | ButtonPressMask |
+ ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask);
+ Tk_CreateEventHandler(tkwin, mask, BindProc, bindPtr);
+ return bindPtr;
+}
+
+void
+Blt_DestroyBindingTable(BindTable *bindPtr)
+{
+ unsigned int mask;
+
+ Tk_DeleteBindingTable(bindPtr->bindingTable);
+ mask = (KeyPressMask | KeyReleaseMask | ButtonPressMask |
+ ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask);
+ Tk_DeleteEventHandler(bindPtr->tkwin, mask, BindProc, bindPtr);
+ free(bindPtr);
+ bindPtr = NULL;
+}
+
+void
+Blt_PickCurrentItem(BindTable *bindPtr)
+{
+ if (bindPtr->activePick) {
+ PickCurrentItem(bindPtr, &bindPtr->pickEvent);
+ }
+}
+
+void
+Blt_DeleteBindings(
+ BindTable *bindPtr,
+ ClientData object)
+{
+ Tk_DeleteAllBindings(bindPtr->bindingTable, object);
+
+ /*
+ * If this is the object currently picked, we need to repick one.
+ */
+ if (bindPtr->currentItem == object) {
+ bindPtr->currentItem = NULL;
+ bindPtr->currentContext = NULL;
+ }
+ if (bindPtr->newItem == object) {
+ bindPtr->newItem = NULL;
+ bindPtr->newContext = NULL;
+ }
+ if (bindPtr->focusItem == object) {
+ bindPtr->focusItem = NULL;
+ bindPtr->focusContext = NULL;
+ }
+}
+
+void
+Blt_MoveBindingTable(
+ BindTable *bindPtr,
+ Tk_Window tkwin)
+{
+ unsigned int mask;
+
+ mask = (KeyPressMask | KeyReleaseMask | ButtonPressMask |
+ ButtonReleaseMask | EnterWindowMask | LeaveWindowMask |
+ PointerMotionMask);
+ if (bindPtr->tkwin != NULL) {
+ Tk_DeleteEventHandler(bindPtr->tkwin, mask, BindProc, bindPtr);
+ }
+ Tk_CreateEventHandler(tkwin, mask, BindProc, bindPtr);
+ bindPtr->tkwin = tkwin;
+}
+
+/*
+ * The following union is used to hold the detail information from an
+ * XEvent (including Tk's XVirtualEvent extension).
+ */
+typedef union {
+ KeySym keySym; /* KeySym that corresponds to xkey.keycode. */
+ int button; /* Button that was pressed (xbutton.button). */
+ Tk_Uid name; /* Tk_Uid of virtual event. */
+ ClientData clientData; /* Used when type of Detail is unknown, and to
+ * ensure that all bytes of Detail are initialized
+ * when this structure is used in a hash key. */
+} Detail;
+
+
+/*
+ * The following structure defines a pattern, which is matched against X
+ * events as part of the process of converting X events into TCL commands.
+ */
+typedef struct {
+ int eventType; /* Type of X event, e.g. ButtonPress. */
+ int needMods; /* Mask of modifiers that must be
+ * present (0 means no modifiers are
+ * required). */
+ Detail detail; /* Additional information that must
+ * match event. Normally this is 0,
+ * meaning no additional information
+ * must match. For KeyPress and
+ * KeyRelease events, a keySym may
+ * be specified to select a
+ * particular keystroke (0 means any
+ * keystrokes). For button events,
+ * specifies a particular button (0
+ * means any buttons are OK). For virtual
+ * events, specifies the Tk_Uid of the
+ * virtual event name (never 0). */
+} Pattern;
+
+typedef struct {
+ const char *name; /* Name of modifier. */
+ int mask; /* Button/modifier mask value, such as
+ * Button1Mask. */
+ int flags; /* Various flags; see below for
+ * definitions. */
+} EventModifier;
+
+/*
+ * Flags for EventModifier structures:
+ *
+ * DOUBLE - Non-zero means duplicate this event,
+ * e.g. for double-clicks.
+ * TRIPLE - Non-zero means triplicate this event,
+ * e.g. for triple-clicks.
+ * QUADRUPLE - Non-zero means quadruple this event,
+ * e.g. for 4-fold-clicks.
+ * MULT_CLICKS - Combination of all of above.
+ */
+
+#define DOUBLE (1<<0)
+#define TRIPLE (1<<1)
+#define QUADRUPLE (1<<2)
+#define MULT_CLICKS (DOUBLE|TRIPLE|QUADRUPLE)
+
+#define META_MASK (AnyModifier<<1)
+#define ALT_MASK (AnyModifier<<2)
+
+typedef struct {
+ const char *name; /* Name of event. */
+ int type; /* Event type for X, such as
+ * ButtonPress. */
+ int eventMask; /* Mask bits (for XSelectInput)
+ * for this event type. */
+} EventInfo;
+
+/*
+ * Note: some of the masks below are an OR-ed combination of
+ * several masks. This is necessary because X doesn't report
+ * up events unless you also ask for down events. Also, X
+ * doesn't report button state in motion events unless you've
+ * asked about button events.
+ */
+
+/*
+ * The defines and table below are used to classify events into
+ * various groups. The reason for this is that logically identical
+ * fields (e.g. "state") appear at different places in different
+ * types of events. The classification masks can be used to figure
+ * out quickly where to extract information from events.
+ */
+
+#define KEY 0x1
+#define BUTTON 0x2
+#define MOTION 0x4
+#define CROSSING 0x8
+#define FOCUS 0x10
+#define EXPOSE 0x20
+#define VISIBILITY 0x40
+#define CREATE 0x80
+#define DESTROY 0x100
+#define UNMAP 0x200
+#define MAP 0x400
+#define REPARENT 0x800
+#define CONFIG 0x1000
+#define GRAVITY 0x2000
+#define CIRC 0x4000
+#define PROP 0x8000
+#define COLORMAP 0x10000
+#define VIRTUAL 0x20000
+#define ACTIVATE 0x40000
+#define MAPREQ 0x80000
+#define CONFIGREQ 0x100000
+#define RESIZEREQ 0x200000
+#define CIRCREQ 0x400000
+
+#define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL)
+#define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|CROSSING|VIRTUAL)
+
+
diff --git a/tlt3.0/bltBind.h b/tlt3.0/bltBind.h
new file mode 100644
index 0000000..937e754
--- /dev/null
+++ b/tlt3.0/bltBind.h
@@ -0,0 +1,120 @@
+/*
+ * bltBind.h --
+ *
+ * Copyright 1998-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_BIND_H
+#define _BLT_BIND_H
+
+#include <bltList.h>
+
+typedef struct _Blt_BindTable *Blt_BindTable;
+
+typedef ClientData (Blt_BindPickProc)(ClientData clientData, int x, int y,
+ ClientData *contextPtr);
+
+typedef void (Blt_BindTagProc)(Blt_BindTable bindTable, ClientData object,
+ ClientData context, Blt_List list);
+
+
+/*
+ * Binding structure information:
+ */
+
+struct _Blt_BindTable {
+ unsigned int flags;
+ Tk_BindingTable bindingTable;
+ /* Table of all bindings currently defined.
+ * NULL means that no bindings exist, so the
+ * table hasn't been created. Each "object"
+ * used for this table is either a Tk_Uid for
+ * a tag or the address of an item named by
+ * id. */
+
+ ClientData currentItem; /* The item currently containing the mouse
+ * pointer, or NULL if none. */
+ ClientData currentContext; /* One word indicating what kind of object was
+ * picked. */
+
+ ClientData newItem; /* The item that is about to become the
+ * current one, or NULL. This field is used
+ * to detect deletions of the new current item
+ * pointer that occur during Leave processing
+ * of the previous current tab. */
+ ClientData newContext; /* One-word indicating what kind of object was
+ * just picked. */
+
+ ClientData focusItem;
+ ClientData focusContext;
+
+ XEvent pickEvent; /* The event upon which the current choice of
+ * the current tab is based. Must be saved so
+ * that if the current item is deleted, we can
+ * pick another. */
+ int activePick; /* The pick event has been initialized so that
+ * we can repick it */
+
+ int state; /* Last known modifier state. Used to defer
+ * picking a new current object while buttons
+ * are down. */
+
+ ClientData clientData;
+ Tk_Window tkwin;
+ Blt_BindPickProc *pickProc; /* Routine to report the item the mouse is
+ * currently over. */
+ Blt_BindTagProc *tagProc; /* Routine to report tags picked items. */
+};
+
+extern void Blt_DestroyBindingTable(Blt_BindTable table);
+
+extern Blt_BindTable Blt_CreateBindingTable(Tcl_Interp *interp,
+ Tk_Window tkwin, ClientData clientData, Blt_BindPickProc *pickProc,
+ Blt_BindTagProc *tagProc);
+
+extern int Blt_ConfigureBindings(Tcl_Interp *interp, Blt_BindTable table,
+ ClientData item, int argc, const char **argv);
+
+extern int Blt_ConfigureBindingsFromObj(Tcl_Interp *interp,
+ Blt_BindTable table, ClientData item, int objc, Tcl_Obj *const *objv);
+
+extern void Blt_PickCurrentItem(Blt_BindTable table);
+
+extern void Blt_DeleteBindings(Blt_BindTable table, ClientData object);
+
+extern void Blt_MoveBindingTable(Blt_BindTable table, Tk_Window tkwin);
+
+#define Blt_SetFocusItem(bindPtr, object, context) \
+ ((bindPtr)->focusItem = (ClientData)(object),\
+ (bindPtr)->focusContext = (ClientData)(context))
+
+#define Blt_SetCurrentItem(bindPtr, object, context) \
+ ((bindPtr)->currentItem = (ClientData)(object),\
+ (bindPtr)->currentContext = (ClientData)(context))
+
+#define Blt_GetCurrentItem(bindPtr) ((bindPtr)->currentItem)
+#define Blt_GetCurrentContext(bindPtr) ((bindPtr)->currentContext)
+#define Blt_GetLatestItem(bindPtr) ((bindPtr)->newItem)
+
+#define Blt_GetBindingData(bindPtr) ((bindPtr)->clientData)
+
+#endif /*_BLT_BIND_H*/
diff --git a/blt3.0.1/src/bltUnixBitmap.c b/tlt3.0/bltBitmap.c
similarity index 84%
copy from blt3.0.1/src/bltUnixBitmap.c
copy to tlt3.0/bltBitmap.c
index 98ce0f8..351ddc4 100644
--- a/blt3.0.1/src/bltUnixBitmap.c
+++ b/tlt3.0/bltBitmap.c
@@ -37,135 +37,19 @@
*
*/
-#include "bltInt.h"
-#include "bltHash.h"
-#ifdef notdef
-#include "bltPicture.h"
-#endif
#include <X11/Xutil.h>
#include <X11/Xproto.h>
+
+#include "bltInt.h"
#include "bltBitmap.h"
+#include "bltMath.h"
+#include "bltHash.h"
#define ROTATE_0 0
#define ROTATE_90 1
#define ROTATE_180 2
#define ROTATE_270 3
-Pixmap
-Blt_PhotoImageMask(Tk_Window tkwin, Tk_PhotoImageBlock src)
-{
- Pixmap bitmap;
- int arraySize, bytes_per_line;
- int offset, count;
- int y;
- unsigned char *bits;
- unsigned char *dp;
-
- bytes_per_line = (src.width + 7) / 8;
- arraySize = src.height * bytes_per_line;
- bits = Blt_AssertMalloc(sizeof(unsigned char) * arraySize);
- dp = bits;
- offset = count = 0;
- for (y = 0; y < src.height; y++) {
- int value, bitMask;
- int x;
- unsigned char *sp;
-
- value = 0, bitMask = 1;
- sp = src.pixelPtr + offset;
- for (x = 0; x < src.width; /*empty*/ ) {
- unsigned long pixel;
-
- pixel = (sp[src.offset[3]] != 0x00);
- if (pixel) {
- value |= bitMask;
- } else {
- count++; /* Count the number of transparent pixels. */
- }
- bitMask <<= 1;
- x++;
- if (!(x & 7)) {
- *dp++ = (unsigned char)value;
- value = 0, bitMask = 1;
- }
- sp += src.pixelSize;
- }
- if (x & 7) {
- *dp++ = (unsigned char)value;
- }
- offset += src.pitch;
- }
- if (count > 0) {
- Tk_MakeWindowExist(tkwin);
- bitmap = XCreateBitmapFromData(Tk_Display(tkwin), Tk_WindowId(tkwin),
- (char *)bits, (unsigned int)src.width, (unsigned int)src.height);
- } else {
- bitmap = None; /* Image is opaque. */
- }
- Blt_Free(bits);
- return bitmap;
-}
-
-#ifdef notdef
-Pixmap
-Blt_PictureMask(Tk_Window tkwin, Picture *srcPtr)
-{
- Blt_Pixel *srcRowPtr;
- Pixmap bitmap;
- int bytesPerLine;
- int count;
- int x, y;
- unsigned char *bits;
- unsigned char *destRowPtr;
-
- bytesPerLine = (srcPtr->width + 7) / 8;
- bits = Blt_AssertMalloc(sizeof(unsigned char)*srcPtr->height*bytesPerLine);
- count = 0;
- srcRowPtr = srcPtr->bits;
- destRowPtr = bits;
- for (y = 0; y < srcPtr->height; y++) {
- int value, bitMask;
- Blt_Pixel *sp;
- unsigned char *dp;
-
- sp = srcRowPtr, dp = destRowPtr;
- value = 0, bitMask = 1;
- for (x = 0; x < srcPtr->width; /*empty*/ ) {
- unsigned long pixel;
-
- pixel = (sp->Alpha != ALPHA_TRANSPARENT);
- if (pixel) {
- value |= bitMask;
- } else {
- count++; /* Count the number of transparent pixels. */
- }
- bitMask <<= 1;
- x++;
- if (!(x & 7)) {
- *dp++ = (unsigned char)value;
- value = 0, bitMask = 1;
- }
- sp++;
- }
- if (x & 7) {
- *dp++ = (unsigned char)value;
- }
- srcRowPtr += srcPtr->pixelsPerRow;
- destRowPtr += bytesPerLine;
- }
- if (count > 0) {
- Tk_MakeWindowExist(tkwin);
- bitmap = XCreateBitmapFromData(Tk_Display(tkwin), Tk_WindowId(tkwin),
- (char *)bits, (unsigned int)srcPtr->width,
- (unsigned int)srcPtr->height);
- } else {
- bitmap = None; /* Image is opaque. */
- }
- Blt_Free(bits);
- return bitmap;
-}
-#endif
-
/*
*---------------------------------------------------------------------------
*
@@ -214,8 +98,8 @@ Blt_RotateBitmap(
ZPixmap);
destImgPtr = XGetImage(display, destBitmap, 0, 0, destWidth, destHeight,
1, ZPixmap);
- angle = FMOD(angle, 360.0);
- if (FMOD(angle, (double)90.0) == 0.0) {
+ angle = fmod(angle, 360.0);
+ if (fmod(angle, (double)90.0) == 0.0) {
int quadrant;
int y;
@@ -509,7 +393,7 @@ Blt_ScaleRotateBitmapArea(
ZPixmap);
destImgPtr = XGetImage(display, destBitmap, 0, 0, regionWidth,
regionHeight, 1, ZPixmap);
- angle = FMOD(angle, 360.0);
+ angle = fmod(angle, 360.0);
Blt_GetBoundingBox(srcWidth, srcHeight, angle, &rotWidth, &rotHeight,
(Point2d *)NULL);
@@ -517,7 +401,7 @@ Blt_ScaleRotateBitmapArea(
xScale = rotWidth / (double)destWidth;
yScale = rotHeight / (double)destHeight;
- if (FMOD(angle, (double)90.0) == 0.0) {
+ if (fmod(angle, (double)90.0) == 0.0) {
int quadrant;
int x, y;
diff --git a/tlt3.0/bltBitmap.h b/tlt3.0/bltBitmap.h
new file mode 100644
index 0000000..9de6b21
--- /dev/null
+++ b/tlt3.0/bltBitmap.h
@@ -0,0 +1,43 @@
+/*
+ * bltBitmap.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_BITMAP_H
+#define _BLT_BITMAP_H
+
+#include <tk.h>
+
+extern Pixmap Blt_ScaleBitmap(Tk_Window tkwin, Pixmap srcBitmap, int srcWidth,
+ int srcHeight, int destWidth, int destHeight);
+
+extern Pixmap Blt_RotateBitmap(Tk_Window tkwin, Pixmap srcBitmap,
+ int srcWidth, int srcHeight, float angle, int *destWidthPtr,
+ int *destHeightPtr);
+
+extern Pixmap Blt_ScaleRotateBitmapArea(Tk_Window tkwin, Pixmap srcBitmap,
+ unsigned int srcWidth, unsigned int srcHeight, int regionX, int regionY,
+ unsigned int regionWidth, unsigned int regionHeight,
+ unsigned int destWidth, unsigned int destHeight, float angle);
+
+#endif
diff --git a/tlt3.0/bltChain.c b/tlt3.0/bltChain.c
new file mode 100644
index 0000000..54797e1
--- /dev/null
+++ b/tlt3.0/bltChain.c
@@ -0,0 +1,520 @@
+
+/*
+ * bltChain.c --
+ *
+ * The module implements a generic linked list package.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+#include "bltChain.h"
+
+#ifndef ALIGN
+#define ALIGN(a) \
+ (((size_t)a + (sizeof(double) - 1)) & (~(sizeof(double) - 1)))
+#endif /* ALIGN */
+
+typedef struct _Blt_ChainLink ChainLink;
+typedef struct _Blt_Chain Chain;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Create --
+ *
+ * Creates a new linked list (chain) structure and initializes its
+ * pointers;
+ *
+ * Results:
+ * Returns a pointer to the newly created chain structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_Chain
+Blt_Chain_Create(void)
+{
+ Chain *chainPtr;
+
+ chainPtr = malloc(sizeof(Chain));
+ if (chainPtr != NULL) {
+ Blt_Chain_Init(chainPtr);
+ }
+ return chainPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_AllocLink --
+ *
+ * Creates a new chain link. Unlink Blt_Chain_NewLink, this routine also
+ * allocates extra memory in the node for data.
+ *
+ * Results:
+ * The return value is the pointer to the newly created entry.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_ChainLink
+Blt_Chain_AllocLink(size_t extraSize)
+{
+ ChainLink *linkPtr;
+ size_t linkSize;
+
+ linkSize = ALIGN(sizeof(ChainLink));
+ linkPtr = calloc(1, linkSize + extraSize);
+ if (extraSize > 0) {
+ /* Point clientData at the memory beyond the normal structure. */
+ linkPtr->clientData = (ClientData)((char *)linkPtr + linkSize);
+ }
+ return linkPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_InitLink --
+ *
+ * Initializes the new link. This routine is for applications that use
+ * their own memory allocation procedures to allocate links.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_InitLink(ChainLink *linkPtr)
+{
+ linkPtr->clientData = NULL;
+ linkPtr->next = linkPtr->prev = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_NewLink --
+ *
+ * Creates a new link.
+ *
+ * Results:
+ * The return value is the pointer to the newly created link.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_ChainLink
+Blt_Chain_NewLink(void)
+{
+ ChainLink *linkPtr;
+
+ linkPtr = malloc(sizeof(ChainLink));
+ linkPtr->clientData = NULL;
+ linkPtr->next = linkPtr->prev = NULL;
+ return linkPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Reset --
+ *
+ * Removes all the links in the chain, freeing the memory used for each
+ * link. Memory pointed to by the link (clientData) is not freed. It's
+ * the caller's responsibility to deallocate it.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_Reset(Chain *chainPtr) /* Chain to clear */
+{
+ if (chainPtr != NULL) {
+ ChainLink *oldPtr;
+ ChainLink *linkPtr = chainPtr->head;
+
+ while (linkPtr != NULL) {
+ oldPtr = linkPtr;
+ linkPtr = linkPtr->next;
+ free(oldPtr);
+ }
+ Blt_Chain_Init(chainPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Destroy
+ *
+ * Frees all the nodes in the chain and deallocates the memory used for
+ * the chain structure itself. It's assumed that the chain was previously
+ * allocated by Blt_Chain_Create.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_Destroy(Chain *chainPtr)
+{
+ if (chainPtr != NULL) {
+ Blt_Chain_Reset(chainPtr);
+ free(chainPtr);
+ chainPtr = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Init --
+ *
+ * Initializes a linked list.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_Init(Chain *chainPtr)
+{
+ chainPtr->nLinks = 0;
+ chainPtr->head = chainPtr->tail = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_LinkAfter --
+ *
+ * Inserts a link after another link. If afterPtr is NULL, then the new
+ * link is prepended to the beginning of the chain.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_LinkAfter(Chain *chainPtr, ChainLink *linkPtr, ChainLink *afterPtr)
+{
+ if (chainPtr->head == NULL) {
+ chainPtr->tail = chainPtr->head = linkPtr;
+ } else {
+ if (afterPtr == NULL) {
+ /* Append to the end of the chain. */
+ linkPtr->next = NULL;
+ linkPtr->prev = chainPtr->tail;
+ chainPtr->tail->next = linkPtr;
+ chainPtr->tail = linkPtr;
+ } else {
+ linkPtr->next = afterPtr->next;
+ linkPtr->prev = afterPtr;
+ if (afterPtr == chainPtr->tail) {
+ chainPtr->tail = linkPtr;
+ } else {
+ afterPtr->next->prev = linkPtr;
+ }
+ afterPtr->next = linkPtr;
+ }
+ }
+ chainPtr->nLinks++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_LinkBefore --
+ *
+ * Inserts a new link preceding a given link in a chain. If beforePtr is
+ * NULL, then the new link is placed at the beginning of the list.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_LinkBefore(Chain *chainPtr, ChainLink *linkPtr, ChainLink *beforePtr)
+{
+ if (chainPtr->head == NULL) {
+ chainPtr->tail = chainPtr->head = linkPtr;
+ } else {
+ if (beforePtr == NULL) {
+ /* Prepend to the front of the chain */
+ linkPtr->next = chainPtr->head;
+ linkPtr->prev = NULL;
+ chainPtr->head->prev = linkPtr;
+ chainPtr->head = linkPtr;
+ } else {
+ linkPtr->prev = beforePtr->prev;
+ linkPtr->next = beforePtr;
+ if (beforePtr == chainPtr->head) {
+ chainPtr->head = linkPtr;
+ } else {
+ beforePtr->prev->next = linkPtr;
+ }
+ beforePtr->prev = linkPtr;
+ }
+ }
+ chainPtr->nLinks++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_UnlinkLink --
+ *
+ * Unlinks a link from the chain. The link is not deallocated, but only
+ * removed from the chain.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_UnlinkLink(Chain *chainPtr, ChainLink *linkPtr)
+{
+ int unlinked; /* Indicates if the link is actually removed
+ * from the chain. */
+
+ unlinked = FALSE;
+ if (chainPtr->head == linkPtr) {
+ chainPtr->head = linkPtr->next;
+ unlinked = TRUE;
+ }
+ if (chainPtr->tail == linkPtr) {
+ chainPtr->tail = linkPtr->prev;
+ unlinked = TRUE;
+ }
+ if (linkPtr->next != NULL) {
+ linkPtr->next->prev = linkPtr->prev;
+ unlinked = TRUE;
+ }
+ if (linkPtr->prev != NULL) {
+ linkPtr->prev->next = linkPtr->next;
+ unlinked = TRUE;
+ }
+ if (unlinked) {
+ chainPtr->nLinks--;
+ }
+ linkPtr->prev = linkPtr->next = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_DeleteLink --
+ *
+ * Unlinks and frees the given link from the chain. It's assumed that
+ * the link belong to the chain. No error checking is performed to verify
+ * this.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_DeleteLink(Blt_Chain chain, Blt_ChainLink link)
+{
+ Blt_Chain_UnlinkLink(chain, link);
+ free(link);
+ link = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Append
+ *
+ * Creates and new link with the given data and appends it to the end of
+ * the chain.
+ *
+ * Results:
+ * Returns a pointer to the link created.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_ChainLink
+Blt_Chain_Append(Blt_Chain chain, ClientData clientData)
+{
+ Blt_ChainLink link;
+
+ link = Blt_Chain_NewLink();
+ Blt_Chain_LinkAfter(chain, link, (Blt_ChainLink)NULL);
+ Blt_Chain_SetValue(link, clientData);
+ return link;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Prepend
+ *
+ * Creates and new link with the given data and prepends it to beginning
+ * of the chain.
+ *
+ * Results:
+ * Returns a pointer to the link created.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_ChainLink
+Blt_Chain_Prepend(Blt_Chain chain, ClientData clientData)
+{
+ Blt_ChainLink link;
+
+ link = Blt_Chain_NewLink();
+ Blt_Chain_LinkBefore(chain, link, (Blt_ChainLink)NULL);
+ Blt_Chain_SetValue(link, clientData);
+ return link;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_GetNthLink --
+ *
+ * Find the link at the given position in the chain. The position
+ * is number from 0. If position is negative is returns the nth
+ * link from the back of the chain.
+ *
+ * Results:
+ * Returns the pointer to the link, if that numbered link
+ * exists. Otherwise NULL.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_ChainLink
+Blt_Chain_GetNthLink(Chain *chainPtr, long position)
+{
+ if (chainPtr != NULL) {
+ if (position < 0) {
+ ChainLink *linkPtr;
+ int i;
+
+ position = -position;
+ for (i = 0, linkPtr = chainPtr->tail; linkPtr != NULL;
+ linkPtr = linkPtr->prev, i++) {
+ if (i == position) {
+ return linkPtr;
+ }
+ }
+ } else {
+ ChainLink *linkPtr;
+ int i;
+
+ linkPtr = chainPtr->head;
+ for (i = 0, linkPtr = chainPtr->head; linkPtr != NULL;
+ linkPtr = linkPtr->next, i++) {
+ if (i == position) {
+ return linkPtr;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_Sort --
+ *
+ * Sorts the chain according to the given comparison routine.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The chain is reordered.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Chain_Sort(Chain *chainPtr, Blt_ChainCompareProc *proc)
+{
+ ChainLink **linkArr;
+ ChainLink *linkPtr;
+ long i;
+
+ if (chainPtr->nLinks < 2) {
+ return;
+ }
+ linkArr = malloc(sizeof(Blt_ChainLink) * (chainPtr->nLinks + 1));
+ if (linkArr == NULL) {
+ return; /* Out of memory. */
+ }
+ i = 0;
+ for (linkPtr = chainPtr->head; linkPtr != NULL;
+ linkPtr = linkPtr->next) {
+ linkArr[i++] = linkPtr;
+ }
+ qsort((char *)linkArr, chainPtr->nLinks, sizeof(Blt_ChainLink),
+ (QSortCompareProc *)proc);
+
+ /* Rethread the chain. */
+ linkPtr = linkArr[0];
+ chainPtr->head = linkPtr;
+ linkPtr->prev = NULL;
+ for (i = 1; i < chainPtr->nLinks; i++) {
+ linkPtr->next = linkArr[i];
+ linkPtr->next->prev = linkPtr;
+ linkPtr = linkPtr->next;
+ }
+ chainPtr->tail = linkPtr;
+ linkPtr->next = NULL;
+ free(linkArr);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Chain_IsBefore --
+ *
+ *
+ * Results:
+ * Return boolean value if the first link comes before the second.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Chain_IsBefore(ChainLink *firstPtr, ChainLink *lastPtr)
+{
+ ChainLink *linkPtr;
+
+ for (linkPtr = firstPtr; linkPtr != NULL; linkPtr = linkPtr->next) {
+ if (linkPtr == lastPtr) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
diff --git a/tlt3.0/bltChain.h b/tlt3.0/bltChain.h
new file mode 100644
index 0000000..7c7cbb0
--- /dev/null
+++ b/tlt3.0/bltChain.h
@@ -0,0 +1,90 @@
+
+/*
+ * bltChain.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _BLT_CHAIN_H
+#define _BLT_CHAIN_H
+
+typedef struct _Blt_Chain *Blt_Chain;
+typedef struct _Blt_ChainLink *Blt_ChainLink;
+
+/*
+ * A Blt_ChainLink is the container structure for the Blt_Chain.
+ */
+
+struct _Blt_ChainLink {
+ Blt_ChainLink prev; /* Link to the previous link */
+ Blt_ChainLink next; /* Link to the next link */
+ ClientData clientData; /* Pointer to the data object */
+};
+
+typedef int (Blt_ChainCompareProc)(Blt_ChainLink *l1Ptr, Blt_ChainLink *l2Ptr);
+
+/*
+ * A Blt_Chain is a doubly chained list structure.
+ */
+struct _Blt_Chain {
+ Blt_ChainLink head; /* Pointer to first element in chain */
+ Blt_ChainLink tail; /* Pointer to last element in chain */
+ long nLinks; /* Number of elements in chain */
+};
+
+extern void Blt_Chain_Init(Blt_Chain chain);
+extern Blt_Chain Blt_Chain_Create(void);
+extern void Blt_Chain_Destroy(Blt_Chain chain);
+extern Blt_ChainLink Blt_Chain_NewLink(void);
+extern Blt_ChainLink Blt_Chain_AllocLink(size_t size);
+extern Blt_ChainLink Blt_Chain_Append(Blt_Chain chain,
+ ClientData clientData);
+extern Blt_ChainLink Blt_Chain_Prepend(Blt_Chain chain,
+ ClientData clientData);
+extern void Blt_Chain_Reset(Blt_Chain chain);
+extern void Blt_Chain_InitLink(Blt_ChainLink link);
+extern void Blt_Chain_LinkAfter(Blt_Chain chain, Blt_ChainLink link,
+ Blt_ChainLink after);
+extern void Blt_Chain_LinkBefore(Blt_Chain chain, Blt_ChainLink link,
+ Blt_ChainLink before);
+extern void Blt_Chain_UnlinkLink(Blt_Chain chain, Blt_ChainLink link);
+extern void Blt_Chain_DeleteLink(Blt_Chain chain, Blt_ChainLink link);
+extern Blt_ChainLink Blt_Chain_GetNthLink(Blt_Chain chain, long position);
+extern void Blt_Chain_Sort(Blt_Chain chain, Blt_ChainCompareProc *proc);
+extern int Blt_Chain_IsBefore(Blt_ChainLink first, Blt_ChainLink last);
+
+#define Blt_Chain_GetLength(c) (((c) == NULL) ? 0 : (c)->nLinks)
+#define Blt_Chain_FirstLink(c) (((c) == NULL) ? NULL : (c)->head)
+#define Blt_Chain_LastLink(c) (((c) == NULL) ? NULL : (c)->tail)
+#define Blt_Chain_PrevLink(l) ((l)->prev)
+#define Blt_Chain_NextLink(l) ((l)->next)
+#define Blt_Chain_GetValue(l) ((l)->clientData)
+#define Blt_Chain_FirstValue(c) (((c)->head == NULL) ? NULL : (c)->head->clientData)
+#define Blt_Chain_SetValue(l, value) ((l)->clientData = (ClientData)(value))
+#define Blt_Chain_AppendLink(c, l) \
+ (Blt_Chain_LinkAfter((c), (l), (Blt_ChainLink)NULL))
+#define Blt_Chain_PrependLink(c, l) \
+ (Blt_Chain_LinkBefore((c), (l), (Blt_ChainLink)NULL))
+
+#endif /* _BLT_CHAIN_H */
diff --git a/tlt3.0/bltConfig.c b/tlt3.0/bltConfig.c
new file mode 100644
index 0000000..8ced073
--- /dev/null
+++ b/tlt3.0/bltConfig.c
@@ -0,0 +1,2024 @@
+
+/*
+ * bltConfig.c --
+ *
+ * This file contains a Tcl_Obj based replacement for the widget
+ * configuration functions in Tk.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Copyright 2003-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is a Tcl_Obj based replacement for the widget configuration
+ * functions in Tk.
+ *
+ * What not use the new Tk_Option interface?
+ *
+ * There were design changes in the new Tk_Option interface that
+ * make it unwieldy.
+ *
+ * o You have to dynamically allocate, store, and deallocate
+ * your option table.
+ * o The Tk_FreeConfigOptions routine requires a tkwin argument.
+ * Unfortunately, most widgets save the display pointer and
+ * de-reference their tkwin when the window is destroyed.
+ * o There's no TK_CONFIG_CUSTOM functionality. This means that
+ * save special options must be saved as strings by
+ * Tk_ConfigureWidget and processed later, thus losing the
+ * benefits of Tcl_Objs. It also make error handling
+ * problematic, since you don't pick up certain errors like
+ *
+ * .widget configure -myoption bad -myoption good
+ *
+ * You will never see the first "bad" value.
+ * o Especially compared to the former Tk_ConfigureWidget calls,
+ * the new interface is overly complex. If there was a big
+ * performance win, it might be worth the effort. But let's
+ * face it, this biggest wins are in processing custom options
+ * values with thousands of elements. Most common resources
+ * (font, color, etc) have string tokens anyways.
+ *
+ * On the other hand, the replacement functions in this file fell
+ * into place quite easily both from the aspect of API writer and
+ * user. The biggest benefit is that you don't need to change lots
+ * of working code just to get the benefits of Tcl_Objs.
+ *
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include "bltInt.h"
+#include "bltWindow.h"
+#include "bltFont.h"
+#include "bltBgStyle.h"
+
+#define PIXELS_NNEG 0
+#define PIXELS_POS 1
+#define PIXELS_ANY 2
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetPixelsFromObj --
+ *
+ * Like Tk_GetPixelsFromObj, but checks for negative, zero.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetPixelsFromObj(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr,
+ int check, /* Can be PIXELS_POS, PIXELS_NNEG,
+ * or PIXELS_ANY, */
+ int *valuePtr)
+{
+ int length;
+
+ if (Tk_GetPixelsFromObj(interp, tkwin, objPtr, &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length >= SHRT_MAX) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": too big to represent", (char *)NULL);
+ return TCL_ERROR;
+ }
+ switch (check) {
+ case PIXELS_NNEG:
+ if (length < 0) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": can't be negative", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case PIXELS_POS:
+ if (length <= 0) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": must be positive", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case PIXELS_ANY:
+ break;
+ }
+ *valuePtr = length;
+ return TCL_OK;
+}
+
+int
+Blt_GetPadFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Window */
+ Tcl_Obj *objPtr, /* Pixel value string */
+ Blt_Pad *padPtr)
+{
+ int side1, side2;
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc < 1) || (objc > 2)) {
+ Tcl_AppendResult(interp, "wrong # elements in padding list",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_GetPixelsFromObj(interp, tkwin, objv[0], PIXELS_NNEG,
+ &side1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ side2 = side1;
+ if ((objc > 1) &&
+ (Blt_GetPixelsFromObj(interp, tkwin, objv[1], PIXELS_NNEG,
+ &side2) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ /* Don't update the pad structure until we know both values are okay. */
+ padPtr->side1 = side1;
+ padPtr->side2 = side2;
+ return TCL_OK;
+}
+
+int
+Blt_GetStateFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tcl_Obj *objPtr, /* Pixel value string */
+ int *statePtr)
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "normal", length) == 0)) {
+ *statePtr = STATE_NORMAL;
+ } else if ((c == 'd') && (strncmp(string, "disabled", length) == 0)) {
+ *statePtr = STATE_DISABLED;
+ } else if ((c == 'a') && (strncmp(string, "active", length) == 0)) {
+ *statePtr = STATE_ACTIVE;
+ } else {
+ Tcl_AppendResult(interp, "bad state \"", string,
+ "\": should be normal, active, or disabled", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+const char *
+Blt_NameOfState(int state)
+{
+ switch (state) {
+ case STATE_ACTIVE:
+ return "active";
+ case STATE_DISABLED:
+ return "disabled";
+ case STATE_NORMAL:
+ return "normal";
+ default:
+ return "???";
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NameOfFill --
+ *
+ * Converts the integer representing the fill style into a string.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_NameOfFill(int fill)
+{
+ switch (fill) {
+ case FILL_X:
+ return "x";
+ case FILL_Y:
+ return "y";
+ case FILL_NONE:
+ return "none";
+ case FILL_BOTH:
+ return "both";
+ default:
+ return "unknown value";
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetFillFromObj --
+ *
+ * Converts the fill style string into its numeric representation.
+ *
+ * Valid style strings are:
+ *
+ * "none" Use neither plane.
+ * "x" X-coordinate plane.
+ * "y" Y-coordinate plane.
+ * "both" Use both coordinate planes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+int
+Blt_GetFillFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *fillPtr)
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
+ *fillPtr = FILL_NONE;
+ } else if ((c == 'x') && (strncmp(string, "x", length) == 0)) {
+ *fillPtr = FILL_X;
+ } else if ((c == 'y') && (strncmp(string, "y", length) == 0)) {
+ *fillPtr = FILL_Y;
+ } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
+ *fillPtr = FILL_BOTH;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", string,
+ "\": should be \"none\", \"x\", \"y\", or \"both\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetDashesFromObj --
+ *
+ * Converts a TCL list of dash values into a dash list ready for
+ * use with XSetDashes.
+ *
+ * A valid list dash values can have zero through 11 elements
+ * (PostScript limit). Values must be between 1 and 255. Although
+ * a list of 0 (like the empty string) means no dashes.
+ *
+ * Results:
+ * A standard TCL result. If the list represented a valid dash
+ * list TCL_OK is returned and *dashesPtr* will contain the
+ * valid dash list. Otherwise, TCL_ERROR is returned and
+ * interp->result will contain an error message.
+ *
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetDashesFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Blt_Dashes *dashesPtr)
+{
+ const char *string;
+ char c;
+
+ string = Tcl_GetString(objPtr);
+ if (string == NULL) {
+ dashesPtr->values[0] = 0;
+ return TCL_OK;
+ }
+ c = string[0];
+ if (c == '\0') {
+ dashesPtr->values[0] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dot") == 0)) {
+ /* 1 */
+ dashesPtr->values[0] = 1;
+ dashesPtr->values[1] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dash") == 0)) {
+ /* 5 2 */
+ dashesPtr->values[0] = 5;
+ dashesPtr->values[1] = 2;
+ dashesPtr->values[2] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dashdot") == 0)) {
+ /* 2 4 2 */
+ dashesPtr->values[0] = 2;
+ dashesPtr->values[1] = 4;
+ dashesPtr->values[2] = 2;
+ dashesPtr->values[3] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dashdotdot") == 0)) {
+ /* 2 4 2 2 */
+ dashesPtr->values[0] = 2;
+ dashesPtr->values[1] = 4;
+ dashesPtr->values[2] = 2;
+ dashesPtr->values[3] = 2;
+ dashesPtr->values[4] = 0;
+ } else {
+ int objc;
+ Tcl_Obj **objv;
+ int i;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > 11) { /* This is the postscript limit */
+ Tcl_AppendResult(interp, "too many values in dash list \"",
+ string, "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ int value;
+
+ if (Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Backward compatibility:
+ * Allow list of 0 to turn off dashes
+ */
+ if ((value == 0) && (objc == 1)) {
+ break;
+ }
+ if ((value < 1) || (value > 255)) {
+ Tcl_AppendResult(interp, "dash value \"",
+ Tcl_GetString(objv[i]), "\" is out of range",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ dashesPtr->values[i] = (unsigned char)value;
+ }
+ /* Make sure the array ends with a NUL byte */
+ dashesPtr->values[i] = 0;
+ }
+ return TCL_OK;
+}
+
+const char *
+Blt_NameOfSide(int side)
+{
+ switch (side) {
+ case SIDE_LEFT:
+ return "left";
+ case SIDE_RIGHT:
+ return "right";
+ case SIDE_BOTTOM:
+ return "bottom";
+ case SIDE_TOP:
+ return "top";
+ }
+ return "unknown side value";
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetSideFromObj --
+ *
+ * Converts the fill style string into its numeric representation.
+ *
+ * Valid style strings are "left", "right", "top", or "bottom".
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED */
+int
+Blt_GetSideFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tcl_Obj *objPtr, /* Value string */
+ int *sidePtr) /* (out) Token representing side:
+ * either SIDE_LEFT, SIDE_RIGHT,
+ * SIDE_TOP, or SIDE_BOTTOM. */
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'l') && (strncmp(string, "left", length) == 0)) {
+ *sidePtr = SIDE_LEFT;
+ } else if ((c == 'r') && (strncmp(string, "right", length) == 0)) {
+ *sidePtr = SIDE_RIGHT;
+ } else if ((c == 't') && (strncmp(string, "top", length) == 0)) {
+ *sidePtr = SIDE_TOP;
+ } else if ((c == 'b') && (strncmp(string, "bottom", length) == 0)) {
+ *sidePtr = SIDE_BOTTOM;
+ } else {
+ Tcl_AppendResult(interp, "bad side \"", string,
+ "\": should be left, right, top, or bottom", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+int
+Blt_GetLimitsFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr,
+ Blt_Limits *limitsPtr)
+{
+ int values[3];
+ int nValues;
+ int limitsFlags;
+
+ /* Initialize limits to default values */
+ values[2] = LIMITS_NOM;
+ values[1] = LIMITS_MAX;
+ values[0] = LIMITS_MIN;
+ limitsFlags = 0;
+ nValues = 0;
+ if (objPtr != NULL) {
+ Tcl_Obj **objv;
+ int objc;
+ int i;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > 3) {
+ Tcl_AppendResult(interp, "wrong # limits \"", Tcl_GetString(objPtr),
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ const char *string;
+ int size;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '\0') {
+ continue; /* Empty string: use default value */
+ }
+ limitsFlags |= (1 << i);
+ if (Tk_GetPixelsFromObj(interp, tkwin, objv[i], &size) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((size < LIMITS_MIN) || (size > LIMITS_MAX)) {
+ Tcl_AppendResult(interp, "bad limit \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ values[i] = size;
+ }
+ nValues = objc;
+ }
+ /*
+ * Check the limits specified. We can't check the requested size of
+ * widgets.
+ */
+ switch (nValues) {
+ case 1:
+ limitsFlags |= (LIMITS_MIN_SET | LIMITS_MAX_SET);
+ values[1] = values[0]; /* Set minimum and maximum to value */
+ break;
+
+ case 2:
+ if (values[1] < values[0]) {
+ Tcl_AppendResult(interp, "bad range \"", Tcl_GetString(objPtr),
+ "\": min > max", (char *)NULL);
+ return TCL_ERROR; /* Minimum is greater than maximum */
+ }
+ break;
+
+ case 3:
+ if (values[1] < values[0]) {
+ Tcl_AppendResult(interp, "bad range \"", Tcl_GetString(objPtr),
+ "\": min > max", (char *)NULL);
+ return TCL_ERROR; /* Minimum is greater than maximum */
+ }
+ if ((values[2] < values[0]) || (values[2] > values[1])) {
+ Tcl_AppendResult(interp, "nominal value \"", Tcl_GetString(objPtr),
+ "\" out of range", (char *)NULL);
+ return TCL_ERROR; /* Nominal is outside of range defined
+ * by minimum and maximum */
+ }
+ break;
+ }
+ limitsPtr->min = values[0];
+ limitsPtr->max = values[1];
+ limitsPtr->nom = values[2];
+ limitsPtr->flags = limitsFlags;
+ return TCL_OK;
+}
+
+/* Configuration option helper routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DoConfig --
+ *
+ * This procedure applies a single configuration option
+ * to a widget record.
+ *
+ * Results:
+ * A standard TCL return value.
+ *
+ * Side effects:
+ * WidgRec is modified as indicated by specPtr and value.
+ * The old value is recycled, if that is appropriate for
+ * the value type.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+DoConfig(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to
+ * set up X resources). */
+ Blt_ConfigSpec *sp, /* Specifier to apply. */
+ Tcl_Obj *objPtr, /* Value to use to fill in widgRec. */
+ char *widgRec) /* Record whose fields are to be
+ * modified. Values must be properly
+ * initialized. */
+{
+ char *ptr;
+ int objIsEmpty;
+
+ objIsEmpty = FALSE;
+ if (objPtr == NULL) {
+ objIsEmpty = TRUE;
+ } else if (sp->specFlags & BLT_CONFIG_NULL_OK) {
+ int length;
+
+ if (objPtr->bytes != NULL) {
+ length = objPtr->length;
+ } else {
+ Tcl_GetStringFromObj(objPtr, &length);
+ }
+ objIsEmpty = (length == 0);
+ }
+ do {
+ ptr = widgRec + sp->offset;
+ switch (sp->type) {
+ case BLT_CONFIG_ANCHOR:
+ {
+ Tk_Anchor anchor;
+
+ if (Tk_GetAnchorFromObj(interp, objPtr, &anchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(Tk_Anchor *)ptr = anchor;
+ }
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ {
+ Pixmap bitmap;
+
+ if (objIsEmpty) {
+ bitmap = None;
+ } else {
+ bitmap = Tk_AllocBitmapFromObj(interp, tkwin, objPtr);
+ if (bitmap == None) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Pixmap *)ptr != None) {
+ Tk_FreeBitmap(Tk_Display(tkwin), *(Pixmap *)ptr);
+ }
+ *(Pixmap *)ptr = bitmap;
+ }
+ break;
+
+ case BLT_CONFIG_BOOLEAN:
+ {
+ int bool;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = bool;
+ }
+ break;
+
+ case BLT_CONFIG_BORDER:
+ {
+ Tk_3DBorder border;
+
+ if (objIsEmpty) {
+ border = NULL;
+ } else {
+ border = Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr);
+ if (border == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_3DBorder *)ptr != NULL) {
+ Tk_Free3DBorder(*(Tk_3DBorder *)ptr);
+ }
+ *(Tk_3DBorder *)ptr = border;
+ }
+ break;
+
+ case BLT_CONFIG_CAP_STYLE:
+ {
+ int cap;
+ Tk_Uid uid;
+
+ uid = Tk_GetUid(Tcl_GetString(objPtr));
+ if (Tk_GetCapStyle(interp, uid, &cap) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = cap;
+ }
+ break;
+
+ case BLT_CONFIG_COLOR:
+ {
+ XColor *color;
+
+ if (objIsEmpty) {
+ color = NULL;
+ } else {
+ color = Tk_GetColor(interp, tkwin,
+ Tk_GetUid(Tcl_GetString(objPtr)));
+ if (color == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(XColor **)ptr != NULL) {
+ Tk_FreeColor(*(XColor **)ptr);
+ }
+ *(XColor **)ptr = color;
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ {
+ Tk_Cursor cursor;
+
+ if (objIsEmpty) {
+ cursor = None;
+ } else {
+ cursor = Tk_AllocCursorFromObj(interp, tkwin, objPtr);
+ if (cursor == None) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_Cursor *)ptr != None) {
+ Tk_FreeCursor(Tk_Display(tkwin), *(Tk_Cursor *)ptr);
+ }
+ *(Tk_Cursor *)ptr = cursor;
+ if (sp->type == BLT_CONFIG_ACTIVE_CURSOR) {
+ Tk_DefineCursor(tkwin, cursor);
+ }
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ if ((*sp->customPtr->parseProc)(sp->customPtr->clientData, interp,
+ tkwin, objPtr, widgRec, sp->offset, sp->specFlags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_DOUBLE:
+ {
+ double value;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(double *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_FONT:
+ {
+ Blt_Font font;
+
+ if (objIsEmpty) {
+ font = NULL;
+ } else {
+ font = Blt_AllocFontFromObj(interp, tkwin, objPtr);
+ if (font == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Blt_Font *)ptr != NULL) {
+ Blt_FreeFont(*(Blt_Font *)ptr);
+ }
+ *(Blt_Font *)ptr = font;
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ {
+ Tk_Font font;
+
+ if (objIsEmpty) {
+ font = NULL;
+ } else {
+ font = Tk_AllocFontFromObj(interp, tkwin, objPtr);
+ if (font == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_Font *)ptr != NULL) {
+ Tk_FreeFont(*(Tk_Font *)ptr);
+ }
+ *(Tk_Font *)ptr = font;
+ }
+ break;
+
+ case BLT_CONFIG_INT:
+ {
+ int value;
+
+ if (Tcl_GetIntFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_JOIN_STYLE:
+ {
+ int join;
+ Tk_Uid uid;
+
+ uid = Tk_GetUid(Tcl_GetString(objPtr));
+ if (Tk_GetJoinStyle(interp, uid, &join) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = join;
+ }
+ break;
+
+ case BLT_CONFIG_JUSTIFY:
+ {
+ Tk_Justify justify;
+
+ if (Tk_GetJustifyFromObj(interp, objPtr, &justify) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(Tk_Justify *)ptr = justify;
+ }
+ break;
+
+ case BLT_CONFIG_MM:
+ {
+ double value;
+
+ if (Tk_GetMMFromObj(interp, tkwin, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(double *)ptr = value;
+ }
+ break;
+
+
+ case BLT_CONFIG_RELIEF:
+ {
+ int relief;
+
+ if (Tk_GetReliefFromObj(interp, objPtr, &relief) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = relief;
+ }
+ break;
+
+ case BLT_CONFIG_STRING:
+ {
+ char *value;
+
+ value = (objIsEmpty) ? NULL :
+ Blt_Strdup(Tcl_GetString(objPtr));
+ if (*(char **)ptr != NULL) {
+ free(*(char **)ptr);
+ *((char **) ptr) = NULL;
+ }
+ *(char **)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_WINDOW:
+ {
+ Tk_Window tkwin2;
+
+ if (objIsEmpty) {
+ tkwin2 = None;
+ } else {
+ const char *path;
+
+ path = Tcl_GetString(objPtr);
+ tkwin2 = Tk_NameToWindow(interp, path, tkwin);
+ if (tkwin2 == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ *(Tk_Window *)ptr = tkwin2;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK:
+ {
+ int bool;
+ unsigned long mask, flags;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ mask = (unsigned long)sp->customPtr;
+ flags = *(int *)ptr;
+ flags &= ~mask;
+ if (bool) {
+ flags |= mask;
+ }
+ *(int *)ptr = flags;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK_INVERT:
+ {
+ int bool;
+ unsigned long mask, flags;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ mask = (unsigned long)sp->customPtr;
+ flags = *(int *)ptr;
+ flags &= ~mask;
+ if (!bool) {
+ flags |= mask;
+ }
+ *(int *)ptr = flags;
+ }
+ break;
+
+ case BLT_CONFIG_DASHES:
+ if (Blt_GetDashesFromObj(interp, objPtr, (Blt_Dashes *)ptr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+
+ case BLT_CONFIG_FILL:
+ if (Blt_GetFillFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_FLOAT:
+ {
+ double value;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(float *)ptr = (float)value;
+ }
+ break;
+
+ case BLT_CONFIG_INT_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+
+ case BLT_CONFIG_INT_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS, &value)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+
+ case BLT_CONFIG_LIST:
+ {
+ const char **argv;
+ int argc;
+
+ if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &argc, &argv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (*(char ***)ptr != NULL) {
+ Tcl_Free((void*)(*(char ***)ptr));
+ *((char ***) ptr) = NULL;
+ }
+ *(const char ***)ptr = argv;
+ }
+ break;
+
+ case BLT_CONFIG_LONG:
+ {
+ long value;
+
+ if (Tcl_GetLongFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_LONG_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+
+ case BLT_CONFIG_LONG_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS, &value)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_OBJ:
+ {
+ Tcl_IncrRefCount(objPtr);
+ if (*(Tcl_Obj **)ptr != NULL) {
+ Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
+ }
+ *(Tcl_Obj **)ptr = objPtr;
+ }
+ break;
+
+ case BLT_CONFIG_PAD:
+ if (Blt_GetPadFromObj(interp, tkwin, objPtr, (Blt_Pad *)ptr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS_NNEG:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr,
+ PIXELS_NNEG, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr, PIXELS_ANY,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS_POS:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr, PIXELS_POS,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_STATE:
+ if (Blt_GetStateFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_SIDE:
+ if (Blt_GetSideFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ {
+ Blt_Background style;
+
+ if (objIsEmpty) {
+ style = NULL;
+ } else {
+ style = Blt_GetBackgroundFromObj(interp, tkwin, objPtr);
+ if (style == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Blt_Background *)ptr != NULL) {
+ Blt_FreeBackground(*(Blt_Background *)ptr);
+ }
+ *(Blt_Background *)ptr = style;
+ }
+ break;
+
+ default:
+ Tcl_AppendResult(interp, "bad config table: unknown type ",
+ Blt_Itoa(sp->type), (char *)NULL);
+ return TCL_ERROR;
+ }
+ sp++;
+ } while ((sp->switchName == NULL) && (sp->type != BLT_CONFIG_END));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FormatConfigValue --
+ *
+ * This procedure formats the current value of a configuration
+ * option.
+ *
+ * Results:
+ * The return value is the formatted value of the option given
+ * by specPtr and widgRec. If the value is static, so that it
+ * need not be freed, *freeProcPtr will be set to NULL; otherwise
+ * *freeProcPtr will be set to the address of a procedure to
+ * free the result, and the caller must invoke this procedure
+ * when it is finished with the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Tcl_Obj *
+FormatConfigValue(
+ Tcl_Interp *interp, /* Interpreter for use in real conversions. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ Blt_ConfigSpec *sp, /* Pointer to information describing option.
+ * Must not point to a synonym option. */
+ char *widgRec) /* Pointer to record holding current
+ * values of info for widget. */
+{
+ char *ptr;
+ const char *string;
+
+ ptr = widgRec + sp->offset;
+ string = "";
+ switch (sp->type) {
+ case BLT_CONFIG_ANCHOR:
+ string = Tk_NameOfAnchor(*(Tk_Anchor *)ptr);
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ if (*(Pixmap *)ptr != None) {
+ string = Tk_NameOfBitmap(Tk_Display(tkwin), *(Pixmap *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_BOOLEAN:
+ return Tcl_NewBooleanObj(*(int *)ptr);
+
+ case BLT_CONFIG_BORDER:
+ if (*(Tk_3DBorder *)ptr != NULL) {
+ string = Tk_NameOf3DBorder(*(Tk_3DBorder *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CAP_STYLE:
+ string = Tk_NameOfCapStyle(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_COLOR:
+ if (*(XColor **)ptr != NULL) {
+ string = Tk_NameOfColor(*(XColor **)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ if (*(Tk_Cursor *)ptr != None) {
+ string = Tk_NameOfCursor(Tk_Display(tkwin), *(Tk_Cursor *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ return (*sp->customPtr->printProc)
+ (sp->customPtr->clientData, interp, tkwin, widgRec,
+ sp->offset, sp->specFlags);
+
+ case BLT_CONFIG_DOUBLE:
+ return Tcl_NewDoubleObj(*(double *)ptr);
+
+ case BLT_CONFIG_FONT:
+ if (*(Blt_Font *)ptr != NULL) {
+ string = Blt_NameOfFont(*(Blt_Font *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ if (*(Tk_Font *)ptr != NULL) {
+ string = Tk_NameOfFont(*(Tk_Font *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_INT:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_JOIN_STYLE:
+ string = Tk_NameOfJoinStyle(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_JUSTIFY:
+ string = Tk_NameOfJustify(*(Tk_Justify *)ptr);
+ break;
+
+ case BLT_CONFIG_MM:
+ return Tcl_NewDoubleObj(*(double *)ptr);
+
+ case BLT_CONFIG_PIXELS:
+ case BLT_CONFIG_PIXELS_POS:
+ case BLT_CONFIG_PIXELS_NNEG:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_RELIEF:
+ string = Tk_NameOfRelief(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_STRING:
+ if (*(char **)ptr != NULL) {
+ string = *(char **)ptr;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK:
+ {
+ unsigned long flag;
+
+ flag = (*(unsigned long *)ptr) & (unsigned long)sp->customPtr;
+ return Tcl_NewBooleanObj((flag != 0));
+ }
+
+ case BLT_CONFIG_BITMASK_INVERT:
+ {
+ unsigned long flag;
+
+ flag = (*(unsigned long *)ptr) & (unsigned long)sp->customPtr;
+ return Tcl_NewBooleanObj((flag == 0));
+ }
+
+ case BLT_CONFIG_DASHES:
+ {
+ unsigned char *p;
+ Tcl_Obj *listObjPtr;
+ Blt_Dashes *dashesPtr = (Blt_Dashes *)ptr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for(p = dashesPtr->values; *p != 0; p++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewIntObj(*p));
+ }
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_INT_NNEG:
+ case BLT_CONFIG_INT_POS:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_FILL:
+ string = Blt_NameOfFill(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_FLOAT:
+ {
+ double x = *(float *)ptr;
+ return Tcl_NewDoubleObj(x);
+ }
+
+ case BLT_CONFIG_LIST:
+ {
+ Tcl_Obj *objPtr, *listObjPtr;
+ char *const *p;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (p = *(char ***)ptr; *p != NULL; p++) {
+ objPtr = Tcl_NewStringObj(*p, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_LONG:
+ return Tcl_NewLongObj(*(long *)ptr);
+
+ case BLT_CONFIG_LONG_NNEG:
+ case BLT_CONFIG_LONG_POS:
+ return Tcl_NewLongObj(*(long *)ptr);
+
+ case BLT_CONFIG_OBJ:
+ if (*(Tcl_Obj **)ptr != NULL) {
+ return *(Tcl_Obj **)ptr;
+ }
+ break;
+
+ case BLT_CONFIG_PAD:
+ {
+ Blt_Pad *padPtr = (Blt_Pad *)ptr;
+ Tcl_Obj *objPtr, *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ objPtr = Tcl_NewIntObj(padPtr->side1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ objPtr = Tcl_NewIntObj(padPtr->side2);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_STATE:
+ string = Blt_NameOfState(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_SIDE:
+ string = Blt_NameOfSide(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ if (*(Blt_Background *)ptr != NULL) {
+ string = Blt_NameOfBackground(*(Blt_Background *)ptr);
+ }
+ break;
+
+ default:
+ string = "?? unknown type ??";
+ }
+ return Tcl_NewStringObj(string, -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FormatConfigInfo --
+ *
+ * Create a valid TCL list holding the configuration information
+ * for a single configuration option.
+ *
+ * Results:
+ * A TCL list, dynamically allocated. The caller is expected to
+ * arrange for this list to be freed eventually.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Tcl_Obj *
+FormatConfigInfo(
+ Tcl_Interp *interp, /* Interpreter to use for things
+ * like floating-point precision. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ Blt_ConfigSpec *sp, /* Pointer to information describing
+ * option. */
+ char *widgRec) /* Pointer to record holding current
+ * values of info for widget. */
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (sp->switchName != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->switchName, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->dbName != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->dbName, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->type == BLT_CONFIG_SYNONYM) {
+ return listObjPtr;
+ }
+ if (sp->dbClass != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->dbClass, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->defValue != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->defValue, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ FormatConfigValue(interp, tkwin, sp, widgRec));
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindConfigSpec --
+ *
+ * Search through a table of configuration specs, looking for
+ * one that matches a given switchName.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL
+ * if nothing matched. In that case an error message is left
+ * in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_ConfigSpec *
+FindConfigSpec(
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Blt_ConfigSpec *specs, /* Pointer to table of configuration
+ * specifications for a widget. */
+ Tcl_Obj *objPtr, /* Name (suitable for use in a "config"
+ * command) identifying particular option. */
+ int needFlags, /* Flags that must be present in matching
+ * entry. */
+ int hateFlags) /* Flags that must NOT be present in
+ * matching entry. */
+{
+ Blt_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
+ Blt_ConfigSpec *sp;
+ const char *string;
+ char c; /* First character of current argument. */
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[1];
+ matchPtr = NULL;
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if (sp->switchName == NULL) {
+ continue;
+ }
+ if ((sp->switchName[1] != c) ||
+ (strncmp(sp->switchName, string, length) != 0)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ if (sp->switchName[length] == 0) {
+ matchPtr = sp;
+ goto gotMatch;
+ }
+ if (matchPtr != NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "ambiguous option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *)NULL;
+ }
+ matchPtr = sp;
+ }
+
+ if (matchPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *)NULL;
+ }
+
+ /*
+ * Found a matching entry. If it's a synonym, then find the
+ * entry that it's a synonym for.
+ */
+
+ gotMatch:
+ sp = matchPtr;
+ if (sp->type == BLT_CONFIG_SYNONYM) {
+ for (sp = specs; /*empty*/; sp++) {
+ if (sp->type == BLT_CONFIG_END) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp,
+ "couldn't find synonym for option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *) NULL;
+ }
+ if ((sp->dbName == matchPtr->dbName) &&
+ (sp->type != BLT_CONFIG_SYNONYM) &&
+ ((sp->specFlags & needFlags) == needFlags) &&
+ !(sp->specFlags & hateFlags)) {
+ break;
+ }
+ }
+ }
+ return sp;
+}
+
+/* Public routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureWidgetFromObj --
+ *
+ * Process command-line options and database options to
+ * fill in fields of a widget record with resources and
+ * other parameters.
+ *
+ * Results:
+ * A standard TCL return value. In case of an error,
+ * the interp's result will hold an error message.
+ *
+ * Side effects:
+ * The fields of widgRec get filled in with information
+ * from argc/argv and the option database. Old information
+ * in widgRec's fields gets recycled.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureWidgetFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to
+ * set up X resources). */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const *objv, /* Command-line options. */
+ char *widgRec, /* Record whose fields are to be
+ * modified. Values must be properly
+ * initialized. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. Also,
+ * may have BLT_CONFIG_OBJV_ONLY set. */
+{
+ Blt_ConfigSpec *sp;
+ int needFlags; /* Specs must contain this set of flags
+ * or else they are not considered. */
+ int hateFlags; /* If a spec contains any bits here, it's
+ * not considered. */
+ int result;
+
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application
+ */
+ Tcl_AppendResult(interp, "NULL main window", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Pass one: scan through all the option specs, replacing strings
+ * with Tk_Uid structs (if this hasn't been done already) and
+ * clearing the BLT_CONFIG_OPTION_SPECIFIED flags.
+ */
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if (!(sp->specFlags & INIT) && (sp->switchName != NULL)) {
+ if (sp->dbName != NULL) {
+ sp->dbName = Tk_GetUid(sp->dbName);
+ }
+ if (sp->dbClass != NULL) {
+ sp->dbClass = Tk_GetUid(sp->dbClass);
+ }
+ if (sp->defValue != NULL) {
+ sp->defValue = Tk_GetUid(sp->defValue);
+ }
+ }
+ sp->specFlags = (sp->specFlags & ~BLT_CONFIG_OPTION_SPECIFIED) | INIT;
+ }
+
+ /*
+ * Pass two: scan through all of the arguments, processing those
+ * that match entries in the specs.
+ */
+ while (objc > 0) {
+ sp = FindConfigSpec(interp, specs, objv[0], needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+
+ /* Process the entry. */
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "value for \"", Tcl_GetString(objv[0]),
+ "\" missing", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (DoConfig(interp, tkwin, sp, objv[1], widgRec) != TCL_OK) {
+ char msg[100];
+
+ sprintf_s(msg, 100, "\n (processing \"%.40s\" option)",
+ sp->switchName);
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ sp->specFlags |= BLT_CONFIG_OPTION_SPECIFIED;
+ objc -= 2, objv += 2;
+ }
+
+ /*
+ * Pass three: scan through all of the specs again; if no
+ * command-line argument matched a spec, then check for info
+ * in the option database. If there was nothing in the
+ * database, then use the default.
+ */
+
+ if ((flags & BLT_CONFIG_OBJV_ONLY) == 0) {
+ Tcl_Obj *objPtr;
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((sp->specFlags & BLT_CONFIG_OPTION_SPECIFIED) ||
+ (sp->switchName == NULL) || (sp->type == BLT_CONFIG_SYNONYM)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ objPtr = NULL;
+ if (sp->dbName != NULL) {
+ Tk_Uid value;
+
+ /* If a resource name was specified, check if there's
+ * also a value was associated with it. This
+ * overrides the default value. */
+ value = Tk_GetOption(tkwin, sp->dbName, sp->dbClass);
+ if (value != NULL) {
+ objPtr = Tcl_NewStringObj(value, -1);
+ }
+ }
+
+ if (objPtr != NULL) {
+ Tcl_IncrRefCount(objPtr);
+ result = DoConfig(interp, tkwin, sp, objPtr, widgRec);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ char msg[200];
+
+ sprintf_s(msg, 200,
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "database entry for", sp->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ } else if ((sp->defValue != NULL) &&
+ ((sp->specFlags & BLT_CONFIG_DONT_SET_DEFAULT) == 0)) {
+
+ /* No resource value is found, use the default value. */
+ objPtr = Tcl_NewStringObj(sp->defValue, -1);
+ Tcl_IncrRefCount(objPtr);
+ result = DoConfig(interp, tkwin, sp, objPtr, widgRec);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ char msg[200];
+
+ sprintf_s(msg, 200,
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "default value for", sp->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureInfoFromObj --
+ *
+ * Return information about the configuration options
+ * for a window, and their current values.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp's result will be modified
+ * hold a description of either a single configuration option
+ * available for "widgRec" via "specs", or all the configuration
+ * options available. In the "all" case, the result will
+ * available for "widgRec" via "specs". The result will
+ * be a list, each of whose entries describes one option.
+ * Each entry will itself be a list containing the option's
+ * name for use on command lines, database name, database
+ * class, default value, and current value (empty string
+ * if none). For options that are synonyms, the list will
+ * contain only two values: name and synonym name. If the
+ * "name" argument is non-NULL, then the only information
+ * returned is that for the named argument (i.e. the corresponding
+ * entry in the overall list is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Blt_ConfigureInfoFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Tcl_Obj *objPtr, /* If non-NULL, indicates a single option
+ * whose info is to be returned. Otherwise
+ * info is returned for all options. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+ Tcl_Obj *listObjPtr, *valueObjPtr;
+ const char *string;
+ int needFlags, hateFlags;
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * If information is only wanted for a single configuration
+ * spec, then handle that one spec specially.
+ */
+
+ Tcl_SetResult(interp, (char *)NULL, TCL_STATIC);
+ if (objPtr != NULL) {
+ sp = FindConfigSpec(interp, specs, objPtr, needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+ valueObjPtr = FormatConfigInfo(interp, tkwin, sp, widgRec);
+ Tcl_SetObjResult(interp, valueObjPtr);
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through all the specs, creating a big list with all
+ * their information.
+ */
+ string = NULL; /* Suppress compiler warning. */
+ if (objPtr != NULL) {
+ string = Tcl_GetString(objPtr);
+ }
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((objPtr != NULL) && (sp->switchName != string)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ if (sp->switchName == NULL) {
+ continue;
+ }
+ valueObjPtr = FormatConfigInfo(interp, tkwin, sp, widgRec);
+ Tcl_ListObjAppendElement(interp, listObjPtr, valueObjPtr);
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureValueFromObj --
+ *
+ * This procedure returns the current value of a configuration
+ * option for a widget.
+ *
+ * Results:
+ * The return value is a standard TCL completion code (TCL_OK or
+ * TCL_ERROR). The interp's result will be set to hold either the value
+ * of the option given by objPtr (if TCL_OK is returned) or
+ * an error message (if TCL_ERROR is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureValueFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Tcl_Obj *objPtr, /* Gives the command-line name for the
+ * option whose value is to be returned. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+ int needFlags, hateFlags;
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+ sp = FindConfigSpec(interp, specs, objPtr, needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+ objPtr = FormatConfigValue(interp, tkwin, sp, widgRec);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeOptions --
+ *
+ * Free up all resources associated with configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any resource in widgRec that is controlled by a configuration
+ * option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate
+ * fashion.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FreeOptions(
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Display *display, /* X display; needed for freeing some
+ * resources. */
+ int needFlags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ char *ptr;
+
+ if ((sp->specFlags & needFlags) != needFlags) {
+ continue;
+ }
+ ptr = widgRec + sp->offset;
+ switch (sp->type) {
+ case BLT_CONFIG_STRING:
+ if (*((char **) ptr) != NULL) {
+ free(*((char **) ptr));
+ *((char **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_COLOR:
+ if (*((XColor **) ptr) != NULL) {
+ Tk_FreeColor(*((XColor **) ptr));
+ *((XColor **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_FONT:
+ if (*((Blt_Font *) ptr) != None) {
+ Blt_FreeFont(*((Blt_Font *) ptr));
+ *((Blt_Font *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ if (*((Tk_Font *) ptr) != None) {
+ Tk_FreeFont(*((Tk_Font *) ptr));
+ *((Tk_Font *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ if (*((Pixmap *) ptr) != None) {
+ Tk_FreeBitmap(display, *((Pixmap *) ptr));
+ *((Pixmap *) ptr) = None;
+ }
+ break;
+
+ case BLT_CONFIG_BORDER:
+ if (*((Tk_3DBorder *) ptr) != NULL) {
+ Tk_Free3DBorder(*((Tk_3DBorder *) ptr));
+ *((Tk_3DBorder *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ if (*((Tk_Cursor *) ptr) != None) {
+ Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
+ *((Tk_Cursor *) ptr) = None;
+ }
+ break;
+
+ case BLT_CONFIG_OBJ:
+ if (*(Tcl_Obj **)ptr != NULL) {
+ Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
+ *(Tcl_Obj **)ptr = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_LIST:
+ if (*((char ***) ptr) != NULL) {
+ Tcl_Free((void*)(*((char ***) ptr)));
+ *((char ***) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ if (*((Blt_Background *)ptr) != NULL) {
+ Blt_FreeBackground(*((Blt_Background *)ptr));
+ *((Blt_Background *)ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ if ((sp->customPtr->freeProc != NULL) && (*(char **)ptr != NULL)) {
+ (*sp->customPtr->freeProc)(sp->customPtr->clientData,
+ display, widgRec, sp->offset);
+ }
+ break;
+
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigModified --
+ *
+ * Given the configuration specifications and one or more option
+ * patterns (terminated by a NULL), indicate if any of the matching
+ * configuration options has been reset.
+ *
+ * Results:
+ * Returns 1 if one of the options has changed, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigModified TCL_VARARGS_DEF(Blt_ConfigSpec *, arg1)
+{
+ va_list argList;
+ Blt_ConfigSpec *specs;
+ Blt_ConfigSpec *sp;
+ const char *option;
+
+ specs = TCL_VARARGS_START(Blt_ConfigSpec *, arg1, argList);
+ while ((option = va_arg(argList, const char *)) != NULL) {
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((Tcl_StringMatch(sp->switchName, option)) &&
+ (sp->specFlags & BLT_CONFIG_OPTION_SPECIFIED)) {
+ va_end(argList);
+ return 1;
+ }
+ }
+ }
+ va_end(argList);
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureComponentFromObj --
+ *
+ * Configures a component of a widget. This is useful for
+ * widgets that have multiple components which aren't uniquely
+ * identified by a Tk_Window. It allows us, for example, set
+ * resources for axes of the graph widget. The graph really has
+ * only one window, but its convenient to specify components in a
+ * hierarchy of options.
+ *
+ * *graph.x.logScale yes
+ * *graph.Axis.logScale yes
+ * *graph.temperature.scaleSymbols yes
+ * *graph.Element.scaleSymbols yes
+ *
+ * This is really a hack to work around the limitations of the Tk
+ * resource database. It creates a temporary window, needed to
+ * call Tk_ConfigureWidget, using the name of the component.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * A temporary window is created merely to pass to Tk_ConfigureWidget.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureComponentFromObj(
+ Tcl_Interp *interp,
+ Tk_Window parent, /* Window to associate with component */
+ const char *name, /* Name of component */
+ const char *className,
+ Blt_ConfigSpec *sp,
+ int objc,
+ Tcl_Obj *const *objv,
+ char *widgRec,
+ int flags)
+{
+ Tk_Window tkwin;
+ int result;
+ char *tmpName;
+ int isTemporary = FALSE;
+
+ tmpName = Blt_Strdup(name);
+
+ /* Window name can't start with an upper case letter */
+ tmpName[0] = tolower(name[0]);
+
+ /*
+ * Create component if a child window by the component's name
+ * doesn't already exist.
+ */
+ tkwin = Blt_FindChild(parent, tmpName);
+ if (tkwin == NULL) {
+ tkwin = Tk_CreateWindow(interp, parent, tmpName, (char *)NULL);
+ isTemporary = TRUE;
+ }
+ if (tkwin == NULL) {
+ Tcl_AppendResult(interp, "can't find window in \"",
+ Tk_PathName(parent), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ assert(Tk_Depth(tkwin) == Tk_Depth(parent));
+ free(tmpName);
+
+ Tk_SetClass(tkwin, className);
+ result = Blt_ConfigureWidgetFromObj(interp, tkwin, sp, objc, objv, widgRec,
+ flags);
+ if (isTemporary) {
+ Tk_DestroyWindow(tkwin);
+ }
+ return result;
+}
diff --git a/tlt3.0/bltConfig.h b/tlt3.0/bltConfig.h
new file mode 100644
index 0000000..aca0e62
--- /dev/null
+++ b/tlt3.0/bltConfig.h
@@ -0,0 +1,326 @@
+/*
+ * bltConfig.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef BLT_CONFIG_H
+#define BLT_CONFIG_H
+
+#ifndef Blt_Offset
+#ifdef offsetof
+#define Blt_Offset(type, field) ((int) offsetof(type, field))
+#else
+#define Blt_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
+#endif
+#endif /* Blt_Offset */
+
+typedef int (Blt_OptionParseProc)(ClientData clientData, Tcl_Interp *interp,
+ Tk_Window tkwin, Tcl_Obj *objPtr, char *widgRec, int offset, int flags);
+typedef Tcl_Obj *(Blt_OptionPrintProc)(ClientData clientData,
+ Tcl_Interp *interp, Tk_Window tkwin, char *widgRec, int offset,
+ int flags);
+typedef void (Blt_OptionFreeProc)(ClientData clientData, Display *display,
+ char *widgRec, int offset);
+
+typedef struct Blt_CustomOption {
+ Blt_OptionParseProc *parseProc; /* Procedure to call to parse
+ * an option and store it in
+ * converted form. */
+
+ Blt_OptionPrintProc *printProc; /* Procedure to return a
+ * Tcl_Obj representing an
+ * existing option value. */
+
+ Blt_OptionFreeProc *freeProc; /* Procedure used to free the
+ * value. */
+
+ ClientData clientData; /* Arbitrary one-word value
+ * used by option parser:
+ * passed to parseProc and
+ * printProc. */
+} Blt_CustomOption;
+
+/*
+ * Structure used to specify information for Tk_ConfigureWidget. Each
+ * structure gives complete information for one option, including
+ * how the option is specified on the command line, where it appears
+ * in the option database, etc.
+ */
+
+typedef struct {
+ int type; /* Type of option, such as
+ * BLT_CONFIG_COLOR; see definitions
+ * below. Last option in table must
+ * have type BLT_CONFIG_END. */
+
+ const char *switchName; /* Switch used to specify option in
+ * argv. NULL means this spec is part
+ * of a group. */
+
+ Tk_Uid dbName; /* Name for option in option
+ * database. */
+
+ Tk_Uid dbClass; /* Class for option in database. */
+
+ Tk_Uid defValue; /* Default value for option if not
+ * specified in command line or
+ * database. */
+
+ int offset; /* Where in widget record to store
+ * value; use Blt_Offset macro to
+ * generate values for this. */
+
+ int specFlags; /* Any combination of the values
+ * defined below; other bits are used
+ * internally by tkConfig.c. */
+
+ Blt_CustomOption *customPtr; /* If type is BLT_CONFIG_CUSTOM then
+ * this is a pointer to info about how
+ * to parse and print the option.
+ * Otherwise it is irrelevant. */
+} Blt_ConfigSpec;
+
+/*
+ * Type values for Blt_ConfigSpec structures. See the user
+ * documentation for details.
+ */
+typedef enum {
+ BLT_CONFIG_ACTIVE_CURSOR,
+ BLT_CONFIG_ANCHOR,
+ BLT_CONFIG_BITMAP,
+ BLT_CONFIG_BOOLEAN,
+ BLT_CONFIG_BORDER,
+ BLT_CONFIG_CAP_STYLE,
+ BLT_CONFIG_COLOR,
+ BLT_CONFIG_CURSOR,
+ BLT_CONFIG_CUSTOM,
+ BLT_CONFIG_DOUBLE,
+ BLT_CONFIG_FONT,
+ BLT_CONFIG_INT,
+ BLT_CONFIG_JOIN_STYLE,
+ BLT_CONFIG_JUSTIFY,
+ BLT_CONFIG_MM,
+ BLT_CONFIG_RELIEF,
+ BLT_CONFIG_STRING,
+ BLT_CONFIG_SYNONYM,
+ BLT_CONFIG_WINDOW,
+
+ BLT_CONFIG_BITMASK,
+ BLT_CONFIG_BITMASK_INVERT,
+ BLT_CONFIG_DASHES,
+ BLT_CONFIG_FILL,
+ BLT_CONFIG_FLOAT,
+ BLT_CONFIG_INT_NNEG, /* 0..N */
+ BLT_CONFIG_INT_POS, /* 1..N */
+ BLT_CONFIG_LIST,
+ BLT_CONFIG_LONG,
+ BLT_CONFIG_LONG_NNEG, /* 0..N */
+ BLT_CONFIG_LONG_POS, /* 1..N */
+ BLT_CONFIG_OBJ,
+ BLT_CONFIG_PAD,
+ BLT_CONFIG_PIXELS_NNEG, /* 1.1c 2m 3.2i excluding negative
+ values. */
+ BLT_CONFIG_PIXELS_POS, /* 1.1c 2m 3.2i excluding negative
+ * values and zero. */
+ BLT_CONFIG_PIXELS, /* 1.1c 2m 3.2i. */
+ BLT_CONFIG_SIDE,
+ BLT_CONFIG_STATE,
+ BLT_CONFIG_BACKGROUND,
+
+ BLT_CONFIG_TK_FONT,
+ BLT_CONFIG_END
+} Blt_ConfigTypes;
+
+/*
+ * Possible values for flags argument to Tk_ConfigureWidget:
+ */
+#define BLT_CONFIG_OBJV_ONLY 1
+
+/*
+ * Possible flag values for Blt_ConfigSpec structures. Any bits at or
+ * above BLT_CONFIG_USER_BIT may be used by clients for selecting
+ * certain entries. Before changing any values here, coordinate with
+ * tkOldConfig.c (internal-use-only flags are defined there).
+ */
+/*
+ * Values for "flags" field of Blt_ConfigSpec structures. Be sure to
+ * coordinate these values with those defined in tk.h
+ * (BLT_CONFIG_COLOR_ONLY, etc.). There must not be overlap!
+ *
+ * INIT - Non-zero means (char *) things have been
+ * converted to Tk_Uid's.
+ */
+#define INIT (1<<0)
+#define BLT_CONFIG_NULL_OK (1<<1)
+#define BLT_CONFIG_COLOR_ONLY (1<<2)
+#define BLT_CONFIG_MONO_ONLY (1<<3)
+#define BLT_CONFIG_DONT_SET_DEFAULT (1<<4)
+#define BLT_CONFIG_OPTION_SPECIFIED (1<<5)
+#define BLT_CONFIG_USER_BIT (1<<8)
+
+
+#define SIDE_LEFT (1<<0)
+#define SIDE_TOP (1<<1)
+#define SIDE_RIGHT (1<<2)
+#define SIDE_BOTTOM (1<<3)
+
+#define STATE_NORMAL (0)
+#define STATE_ACTIVE (1<<0)
+#define STATE_DISABLED (1<<1)
+#define STATE_EMPHASIS (1<<2)
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Pad --
+ *
+ * Specifies vertical and horizontal padding.
+ *
+ * Padding can be specified on a per side basis. The fields
+ * side1 and side2 refer to the opposite sides, either
+ * horizontally or vertically.
+ *
+ * side1 side2
+ * ----- -----
+ * x | left right
+ * y | top bottom
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned short int side1, side2;
+} Blt_Pad;
+
+#define padLeft xPad.side1
+#define padRight xPad.side2
+#define padTop yPad.side1
+#define padBottom yPad.side2
+#define PADDING(x) ((x).side1 + (x).side2)
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * The following enumerated values are used as bit flags.
+ * FILL_NONE Neither coordinate plane is specified
+ * FILL_X Horizontal plane.
+ * FILL_Y Vertical plane.
+ * FILL_BOTH Both vertical and horizontal planes.
+ *
+ *---------------------------------------------------------------------------
+ */
+#define FILL_NONE 0
+#define FILL_X 1
+#define FILL_Y 2
+#define FILL_BOTH 3
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Dashes --
+ *
+ * List of dash values (maximum 11 based upon PostScript limit).
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned char values[12];
+ int offset;
+} Blt_Dashes;
+
+#define LineIsDashed(d) ((d).values[0] != 0)
+
+/*
+ * Blt_Limits --
+ *
+ * Defines the bounding of a size (width or height) in the paneset. It may
+ * be related to the widget, pane or paneset size.
+ */
+typedef struct {
+ int flags; /* Flags indicate whether using default
+ * values for limits or not. See flags
+ * below. */
+ int max, min; /* Values for respective limits. */
+ int nom; /* Nominal starting value. */
+} Blt_Limits;
+
+#define LIMITS_MIN_SET (1<<0)
+#define LIMITS_MAX_SET (1<<1)
+#define LIMITS_NOM_SET (1<<2)
+
+#define LIMITS_MIN 0 /* Default minimum limit */
+#define LIMITS_MAX SHRT_MAX /* Default maximum limit */
+#define LIMITS_NOM -1000 /* Default nomimal value. Indicates
+ * if a pane has received any space
+ * yet */
+
+extern void Blt_SetDashes (Display *display, GC gc, Blt_Dashes *dashesPtr);
+extern Blt_Dashes *Blt_GetDashes (GC gc);
+
+extern int Blt_GetLimitsFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, Blt_Limits *limitsPtr);
+
+extern int Blt_ConfigureInfoFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Blt_ConfigSpec *specs, char *widgRec, Tcl_Obj *objPtr, int flags);
+
+extern int Blt_ConfigureValueFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Blt_ConfigSpec *specs, char *widgRec, Tcl_Obj *objPtr, int flags);
+
+extern int Blt_ConfigureWidgetFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Blt_ConfigSpec *specs, int objc, Tcl_Obj *const *objv, char *widgRec,
+ int flags);
+
+extern int Blt_ConfigureComponentFromObj(Tcl_Interp *interp,
+ Tk_Window tkwin, const char *name, const char *className,
+ Blt_ConfigSpec *specs, int objc, Tcl_Obj *const *objv, char *widgRec,
+ int flags);
+
+extern int Blt_ConfigModified TCL_VARARGS(Blt_ConfigSpec *, specs);
+
+extern const char *Blt_NameOfState(int state);
+extern const char *Blt_NameOfSide(int side);
+
+extern void Blt_FreeOptions(Blt_ConfigSpec *specs, char *widgRec,
+ Display *display, int needFlags);
+
+extern int Blt_GetSideFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int *sidePtr);
+
+extern int Blt_GetPixelsFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, int flags, int *valuePtr);
+
+extern int Blt_GetPadFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr, Blt_Pad *padPtr);
+
+extern int Blt_GetStateFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int *statePtr);
+
+extern int Blt_GetFillFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int *fillPtr);
+
+extern int Blt_GetDashesFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Blt_Dashes *dashesPtr);
+
+#endif /* BLT_CONFIG_H */
diff --git a/tlt3.0/bltDBuffer.c b/tlt3.0/bltDBuffer.c
new file mode 100644
index 0000000..4a64280
--- /dev/null
+++ b/tlt3.0/bltDBuffer.c
@@ -0,0 +1,323 @@
+
+/*
+ * bltDBuffer.c --
+ *
+ * This module implements a dynamic buffer for the BLT toolkit.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+#include "bltDBuffer.h"
+#include "bltBase64.h"
+
+typedef struct _Blt_DBuffer DBuffer;
+
+void
+Blt_DBuffer_Init(DBuffer *srcPtr)
+{
+ srcPtr->bytes = NULL;
+ srcPtr->cursor = srcPtr->count = srcPtr->nBytes = 0;
+ srcPtr->chunk = 64;
+}
+
+void
+Blt_DBuffer_Free(DBuffer *srcPtr)
+{
+ if ((srcPtr->bytes != NULL) && (srcPtr->nBytes > 0)) {
+ free(srcPtr->bytes);
+ srcPtr->bytes=NULL;
+ }
+ Blt_DBuffer_Init(srcPtr);
+}
+
+Blt_DBuffer
+Blt_DBuffer_Create(void)
+{
+ DBuffer *srcPtr;
+
+ srcPtr = malloc(sizeof(DBuffer));
+ Blt_DBuffer_Init(srcPtr);
+ return srcPtr;
+}
+
+void
+Blt_DBuffer_Destroy(DBuffer *srcPtr)
+{
+ Blt_DBuffer_Free(srcPtr);
+ free(srcPtr);
+ srcPtr = NULL;
+}
+
+int
+Blt_DBuffer_Resize(DBuffer *srcPtr, size_t nBytes)
+{
+ if (srcPtr->nBytes <= nBytes) {
+ size_t size, wanted;
+ unsigned char *bytes;
+
+ wanted = nBytes + 1;
+ size = srcPtr->chunk;
+
+ /*
+ * Double the buffer size until we have enough room or hit 64K. After
+ * 64K, increase by multiples of 64K.
+ */
+ while ((size <= wanted) && (size < (1<<16))) {
+ size += size;
+ }
+ srcPtr->chunk = size;
+ while (size <= wanted) {
+ size += srcPtr->chunk;
+ }
+ if (srcPtr->bytes == NULL) {
+ bytes = malloc(size);
+ } else {
+ bytes = realloc(srcPtr->bytes, size);
+ }
+ if (bytes == NULL) {
+ return FALSE;
+ }
+ srcPtr->bytes = bytes;
+ srcPtr->nBytes = size;
+ }
+ return TRUE;
+}
+
+unsigned char *
+Blt_DBuffer_Extend(DBuffer *srcPtr, size_t nBytes)
+{
+ unsigned char *bp;
+
+ if (!Blt_DBuffer_Resize(srcPtr, srcPtr->count + nBytes)) {
+ return NULL;
+ }
+ bp = srcPtr->bytes + srcPtr->count;
+ srcPtr->count += nBytes;
+ return bp;
+}
+
+void
+Blt_DBuffer_AppendByte(DBuffer *destPtr, unsigned char value)
+{
+ if (Blt_DBuffer_Resize(destPtr, destPtr->count + sizeof(value))) {
+ destPtr->bytes[destPtr->count] = value;
+ destPtr->count++;
+ }
+}
+
+void
+Blt_DBuffer_AppendShort(DBuffer *destPtr, unsigned short value)
+{
+ if (Blt_DBuffer_Resize(destPtr, destPtr->count + sizeof(value))) {
+ unsigned char *bp;
+
+ bp = destPtr->bytes + destPtr->count;
+#ifdef WORDS_BIGENDIAN
+ bp[0] = (value >> 8) & 0xFF;
+ bp[1] = (value) & 0xFF;
+#else
+ bp[0] = (value) & 0xFF;
+ bp[1] = (value >> 8) & 0xFF;
+#endif
+ destPtr->count += 2;
+ }
+}
+
+void
+Blt_DBuffer_AppendLong(DBuffer *destPtr, unsigned int value)
+{
+ if (Blt_DBuffer_Resize(destPtr, destPtr->count + sizeof(value))) {
+ unsigned char *bp;
+
+ bp = destPtr->bytes + destPtr->count;
+#ifdef WORDS_BIGENDIAN
+ bp[0] = (value >> 24) & 0xFF;
+ bp[1] = (value >> 16) & 0xFF;
+ bp[2] = (value >> 8) & 0xFF;
+ bp[3] = (value) & 0xFF;
+#else
+ bp[0] = (value) & 0xFF;
+ bp[1] = (value >> 8) & 0xFF;
+ bp[2] = (value >> 16) & 0xFF;
+ bp[3] = (value >> 24) & 0xFF;
+#endif
+ destPtr->count += 4;
+ }
+}
+
+Tcl_Obj *
+Blt_DBuffer_ByteArrayObj(DBuffer *srcPtr)
+{
+ return Tcl_NewByteArrayObj(srcPtr->bytes, srcPtr->count);
+}
+
+Tcl_Obj *
+Blt_DBuffer_StringObj(DBuffer *srcPtr)
+{
+ return Tcl_NewStringObj((char *)srcPtr->bytes, srcPtr->count);
+}
+
+int
+Blt_DBuffer_AppendData(DBuffer *srcPtr, const unsigned char *data,
+ size_t nBytes)
+{
+ unsigned char *bp;
+
+ bp = Blt_DBuffer_Extend(srcPtr, nBytes);
+ if (bp == NULL) {
+ return FALSE;
+ }
+ memcpy(bp, data, nBytes);
+ return TRUE;
+}
+
+void
+Blt_DBuffer_VarAppend
+TCL_VARARGS_DEF(DBuffer *, arg1)
+{
+ DBuffer *srcPtr;
+ va_list args;
+
+ srcPtr = TCL_VARARGS_START(DBuffer, arg1, args);
+ for (;;) {
+ const unsigned char *string;
+
+ string = va_arg(args, const unsigned char *);
+ if (string == NULL) {
+ break;
+ }
+ Blt_DBuffer_AppendData(srcPtr, string, strlen((const char *)string));
+ }
+}
+
+void
+Blt_DBuffer_Print
+TCL_VARARGS_DEF(DBuffer *, arg1)
+{
+ DBuffer *srcPtr;
+ char *fmt;
+ char string[BUFSIZ+4];
+ int length;
+ va_list args;
+
+ srcPtr = TCL_VARARGS_START(DBuffer, arg1, args);
+ fmt = va_arg(args, char *);
+ length = vsnprintf(string, BUFSIZ, fmt, args);
+ if (length > BUFSIZ) {
+ strcat(string, "...");
+ }
+ va_end(args);
+ Blt_DBuffer_AppendData(srcPtr, (unsigned char *)string, strlen(string));
+}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+int
+Blt_DBuffer_LoadFile(
+ Tcl_Interp *interp,
+ const char *fileName,
+ Blt_DBuffer dBuffer)
+{
+ int nBytes;
+ Tcl_Channel channel;
+
+ if (fileName[0] == '@') {
+ int mode;
+
+ /* If the file name starts with a '@', then it represents the name of
+ * a previously opened channel. Verify that the channel was opened
+ * for reading. */
+ fileName++;
+ channel = Tcl_GetChannel(interp, fileName, &mode);
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "can't read from \"", fileName, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ channel = Tcl_OpenFileChannel(interp, fileName, "r", 0);
+ }
+ if (channel == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, channel, "-encoding", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, channel, "-translation", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_DBuffer_Init(dBuffer);
+ nBytes = 0;
+ while (!Tcl_Eof(channel)) {
+ int nRead;
+#define BUFFER_SIZE (1<<16)
+ char *bp;
+
+ bp = (char *)Blt_DBuffer_Extend(dBuffer, BUFFER_SIZE);
+ nRead = Tcl_ReadRaw(channel, bp, BUFFER_SIZE);
+ if (nRead == -1) {
+ Tcl_AppendResult(interp, "error reading ", fileName, ": ",
+ Tcl_PosixError(interp), (char *)NULL);
+ Blt_DBuffer_Free(dBuffer);
+ return TCL_ERROR;
+ }
+ nBytes += nRead;
+ Blt_DBuffer_SetLength(dBuffer, nBytes);
+ }
+ Tcl_Close(interp, channel);
+ return TCL_OK;
+}
+
+int
+Blt_DBuffer_DecodeBase64(Tcl_Interp *interp, const char *string, size_t length,
+ DBuffer *destPtr)
+{
+ unsigned char *bp;
+
+ bp = Blt_Base64_Decode(interp, string, &length);
+ if (bp == NULL) {
+ return TCL_ERROR;
+ }
+ if (destPtr->bytes != NULL) {
+ free(destPtr->bytes);
+ destPtr->bytes = NULL;
+ }
+ destPtr->bytes = bp;
+ destPtr->nBytes = destPtr->count = length;
+ destPtr->cursor = 0;
+ destPtr->chunk = 64;
+ return TCL_OK;
+}
+
+
+char *
+Blt_DBuffer_EncodeBase64(
+ Tcl_Interp *interp, /* Interpreter to report errors to. */
+ DBuffer *srcPtr) /* Input binary buffer. */
+{
+ return Blt_Base64_Encode(interp, srcPtr->bytes, srcPtr->count);
+}
+
diff --git a/tlt3.0/bltDBuffer.h b/tlt3.0/bltDBuffer.h
new file mode 100644
index 0000000..0d08b1d
--- /dev/null
+++ b/tlt3.0/bltDBuffer.h
@@ -0,0 +1,92 @@
+
+/*
+ * bltDBuffer.h --
+ *
+ * Copyright 2003-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_DBUFFER_H
+#define _BLT_DBUFFER_H
+
+typedef struct _Blt_DBuffer {
+ unsigned char *bytes; /* Stores output (malloc-ed).*/
+ size_t nBytes; /* Size of dynamically allocated buffer. */
+
+ size_t count; /* # of bytes read into the buffer. Marks the
+ * # current fill point of the buffer. */
+ size_t cursor; /* Current position in buffer. */
+ size_t chunk; /* Buffer growth size. */
+
+} *Blt_DBuffer;
+
+extern void Blt_DBuffer_VarAppend TCL_VARARGS(Blt_DBuffer, buffer);
+
+extern void Blt_DBuffer_Print TCL_VARARGS(Blt_DBuffer, buffer);
+
+extern void Blt_DBuffer_Init(Blt_DBuffer buffer);
+extern void Blt_DBuffer_Free(Blt_DBuffer buffer);
+extern unsigned char *Blt_DBuffer_Extend(Blt_DBuffer buffer, size_t extra);
+extern int Blt_DBuffer_AppendData(Blt_DBuffer buffer,
+ const unsigned char *bytes, size_t extra);
+extern int Blt_DBuffer_Resize(Blt_DBuffer buffer, size_t length);
+extern Blt_DBuffer Blt_DBuffer_Create(void);
+extern void Blt_DBuffer_Destroy(Blt_DBuffer buffer);
+
+extern int Blt_DBuffer_LoadFile(Tcl_Interp *interp, const char *fileName,
+ Blt_DBuffer buffer);
+
+extern void Blt_DBuffer_AppendByte(Blt_DBuffer buffer, unsigned char byte);
+extern void Blt_DBuffer_AppendShort(Blt_DBuffer buffer,
+ unsigned short value);
+extern void Blt_DBuffer_AppendLong(Blt_DBuffer buffer, unsigned int value);
+extern Tcl_Obj *Blt_DBuffer_ByteArrayObj(Blt_DBuffer buffer);
+extern Tcl_Obj *Blt_DBuffer_StringObj(Blt_DBuffer buffer);
+
+#define Blt_DBuffer_Bytes(s) ((s)->bytes)
+#define Blt_DBuffer_Size(s) ((s)->nBytes)
+
+#define Blt_DBuffer_BytesLeft(s) ((s)->count - (s)->cursor)
+#define Blt_DBuffer_NextByte(s) ((s)->bytes[(s)->cursor++])
+#define Blt_DBuffer_Pointer(s) ((s)->bytes + (s)->cursor)
+#define Blt_DBuffer_SetPointer(s,p) ((s)->cursor = (p) - (s)->bytes)
+
+#define Blt_DBuffer_ResetCursor(s) ((s)->cursor = 0)
+#define Blt_DBuffer_Cursor(s) ((s)->cursor)
+#define Blt_DBuffer_SetCursor(s,n) ((s)->cursor = (n))
+#define Blt_DBuffer_IncrCursor(s,i) ((s)->cursor += (i))
+
+#define Blt_DBuffer_End(s) ((s)->bytes + (s)->count)
+#define Blt_DBuffer_Length(s) ((s)->count)
+#define Blt_DBuffer_SetLengthFromPointer(s,p) \
+ ((s)->count = ((p) - (s)->bytes))
+#define Blt_DBuffer_SetLength(s,i) \
+ ((s)->count = (i), (s)->bytes[(s)->count] = '\0')
+#define Blt_DBuffer_IncrLength(s,i) ((s)->count += (i))
+
+extern int Blt_DBuffer_DecodeBase64(Tcl_Interp *interp,
+ const char *string, size_t length, Blt_DBuffer buffer);
+extern char *Blt_DBuffer_EncodeBase64(Tcl_Interp *interp,
+ Blt_DBuffer buffer);
+
+extern int Blt_IsBase64(const unsigned char *bytes, size_t length);
+
+#endif /*_BLT_DBUFFER_H*/
diff --git a/tlt3.0/bltFont.h b/tlt3.0/bltFont.h
new file mode 100644
index 0000000..272be02
--- /dev/null
+++ b/tlt3.0/bltFont.h
@@ -0,0 +1,137 @@
+
+/*
+ * bltFont.h --
+ *
+ * Copyright 1993-2004 George A Howlett.v
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_FONT_H
+#define _BLT_FONT_H
+
+#define FONT_ITALIC (1<<0)
+#define FONT_BOLD (1<<1)
+
+typedef struct {
+ int ascent; /* The amount in pixels that the tallest
+ * letter sticks up above the baseline, plus
+ * any extra blank space added by the designer
+ * of the font. */
+ int descent; /* The largest amount in pixels that any
+ * letter sticks below the baseline, plus any
+ * extra blank space added by the designer of
+ * the font. */
+ int linespace; /* The sum of the ascent and descent. How
+ * far apart two lines of text in the same
+ * font should be placed so that none of the
+ * characters in one line overlap any of the
+ * characters in the other line. */
+ int tabWidth; /* Width of tabs in this font (pixels). */
+ int underlinePos; /* Offset from baseline to origin of
+ * underline bar (used for drawing underlines
+ * on a non-underlined font). */
+ int underlineHeight; /* Height of underline bar (used for drawing
+ * underlines on a non-underlined font). */
+} Blt_FontMetrics;
+
+
+typedef struct _Blt_Font *Blt_Font;
+typedef struct Blt_FontClass Blt_FontClass;
+
+typedef const char *(Blt_NameOfFontProc)(Blt_Font font);
+typedef void (Blt_GetFontMetricsProc)(Blt_Font font,
+ Blt_FontMetrics *metricsPtr);
+typedef Font (Blt_FontIdProc)(Blt_Font font);
+typedef int (Blt_TextStringWidthProc)(Blt_Font font, const char *string,
+ int nBytes);
+typedef void (Blt_FreeFontProc)(Blt_Font font);
+typedef int (Blt_MeasureCharsProc)(Blt_Font font, const char *text, int nBytes,
+ int maxLength, int flags, int *lengthPtr);
+typedef void (Blt_DrawCharsProc)(Display *display, Drawable drawable, GC gc,
+ Blt_Font font, int depth, float angle, const char *text, int length,
+ int x, int y);
+typedef int (Blt_PostscriptFontNameProc)(Blt_Font font, Tcl_DString *resultPtr);
+typedef const char *(Blt_FamilyOfFontProc)(Blt_Font font);
+typedef int (Blt_CanRotateFontProc)(Blt_Font font, float angle);
+typedef void (Blt_UnderlineCharsProc)(Display *display, Drawable drawable,
+ GC gc, Blt_Font font, const char *text, int textLen, int x, int y,
+ int first, int last, int xMax);
+
+struct Blt_FontClass {
+ int type; /* Indicates the type of font used. */
+ Blt_NameOfFontProc *nameOfFont;
+ Blt_FamilyOfFontProc *familyOfFont;
+ Blt_FontIdProc *fontId;
+ Blt_GetFontMetricsProc *getFontMetrics;
+ Blt_MeasureCharsProc *measureChars;
+ Blt_TextStringWidthProc *textWidth;
+ Blt_CanRotateFontProc *canRotateFont;
+ Blt_DrawCharsProc *drawChars;
+ Blt_PostscriptFontNameProc *postscriptFontName;
+ Blt_FreeFontProc *freeFont;
+ Blt_UnderlineCharsProc *underlineChars;
+};
+
+struct _Blt_Font {
+ void *clientData;
+ Tcl_Interp *interp;
+ Display *display;
+ Blt_FontClass *classPtr;
+};
+
+#define Blt_NameOfFont(f) (*(f)->classPtr->nameOfFont)(f)
+#define Blt_FontId(f) (*(f)->classPtr->fontId)(f)
+#define Blt_MeasureChars(f,s,l,ml,fl,lp) \
+ (*(f)->classPtr->measureChars)(f,s,l,ml,fl,lp)
+#define Blt_DrawChars(d,w,gc,f,dp,a,t,l,x,y) \
+ (*(f)->classPtr->drawChars)(d,w,gc,f,dp,a,t,l,x,y)
+#define Blt_PostscriptFontName(f,rp) (*(f)->classPtr->postscriptFontName)(f,rp)
+#define Blt_FamilyOfFont(f) (*(f)->classPtr->familyOfFont)(f)
+#define Blt_CanRotateFont(f,a) (*(f)->classPtr->canRotateFont)(f,a)
+#define Blt_FreeFont(f) (*(f)->classPtr->freeFont)(f)
+#define Blt_UnderlineChars(d,w,g,f,s,l,x,y,a,b,m) \
+ (*(f)->classPtr->underlineChars)(d,w,g,f,s,l,x,y,a,b,m)
+
+extern Blt_Font Blt_GetFont(Tcl_Interp *interp, Tk_Window tkwin,
+ const char *string);
+extern Blt_Font Blt_AllocFontFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+
+extern void Blt_DrawCharsWithEllipsis(Tk_Window tkwin, Drawable drawable,
+ GC gc, Blt_Font font, int depth, float angle, const char *string,
+ int nBytes, int x, int y, int maxLength);
+
+extern Blt_Font Blt_GetFontFromObj(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr);
+
+extern void Blt_GetFontMetrics(Blt_Font font, Blt_FontMetrics *fmPtr);
+extern int Blt_TextWidth(Blt_Font font, const char *string, int length);
+extern Tcl_Interp *Blt_GetFontInterp(Blt_Font font);
+
+extern const char *Blt_GetFontFileFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, double *sizePtr);
+extern const char *Blt_GetFontFile(Tcl_Interp *interp, const char *spec,
+ double *sizePtr);
+
+#endif /* _BLT_FONT_H */
diff --git a/tlt3.0/bltGrAxis.c b/tlt3.0/bltGrAxis.c
new file mode 100644
index 0000000..faa186b
--- /dev/null
+++ b/tlt3.0/bltGrAxis.c
@@ -0,0 +1,5564 @@
+
+/*
+ * bltGrAxis.c --
+ *
+ * This module implements coordinate axes for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltGrElem.h"
+
+#define MAXTICKS 10001
+
+#define FCLAMP(x) ((((x) < 0.0) ? 0.0 : ((x) > 1.0) ? 1.0 : (x)))
+
+/*
+ * Round x in terms of units
+ */
+#define UROUND(x,u) (Round((x)/(u))*(u))
+#define UCEIL(x,u) (ceil((x)/(u))*(u))
+#define UFLOOR(x,u) (floor((x)/(u))*(u))
+
+#define NUMDIGITS 15 /* Specifies the number of digits of
+ * accuracy used when outputting axis
+ * tick labels. */
+enum TickRange {
+ AXIS_TIGHT, AXIS_LOOSE, AXIS_ALWAYS_LOOSE
+};
+
+#define AXIS_PAD_TITLE 2 /* Padding for axis title. */
+
+/* Axis flags: */
+
+#define AXIS_AUTO_MAJOR (1<<16) /* Auto-generate major ticks. */
+#define AXIS_AUTO_MINOR (1<<17) /* Auto-generate minor ticks. */
+#define AXIS_USE (1<<18) /* Axis is displayed on the screen via
+ * the "use" operation */
+#define AXIS_GRID (1<<19) /* Display grid lines. */
+#define AXIS_GRIDMINOR (1<<20) /* Display grid lines for minor
+ * ticks. */
+#define AXIS_SHOWTICKS (1<<21) /* Display axis ticks. */
+#define AXIS_EXTERIOR (1<<22) /* Axis is exterior to the plot. */
+#define AXIS_CHECK_LIMITS (1<<23) /* Validate user-defined axis limits. */
+
+#define HORIZMARGIN(m) (!((m)->site & 0x1)) /* Even sites are horizontal */
+
+typedef struct {
+ int axis; /* Length of the axis. */
+ int t1; /* Length of a major tick (in
+ * pixels). */
+ int t2; /* Length of a minor tick (in
+ * pixels). */
+ int label; /* Distance from axis to tick label. */
+} AxisInfo;
+
+typedef struct {
+ const char *name;
+ ClassId classId;
+ int margin, invertMargin;
+} AxisName;
+
+static AxisName axisNames[] = {
+ { "x", CID_AXIS_X, MARGIN_BOTTOM, MARGIN_LEFT },
+ { "y", CID_AXIS_Y, MARGIN_LEFT, MARGIN_BOTTOM },
+ { "x2", CID_AXIS_X, MARGIN_TOP, MARGIN_RIGHT },
+ { "y2", CID_AXIS_Y, MARGIN_RIGHT, MARGIN_TOP }
+} ;
+static int nAxisNames = sizeof(axisNames) / sizeof(AxisName);
+
+static Blt_OptionParseProc ObjToLimitProc;
+static Blt_OptionPrintProc LimitToObjProc;
+static Blt_CustomOption limitOption = {
+ ObjToLimitProc, LimitToObjProc, NULL, (ClientData)0
+};
+
+static Blt_OptionFreeProc FreeTicksProc;
+static Blt_OptionParseProc ObjToTicksProc;
+static Blt_OptionPrintProc TicksToObjProc;
+static Blt_CustomOption majorTicksOption = {
+ ObjToTicksProc, TicksToObjProc, FreeTicksProc, (ClientData)AXIS_AUTO_MAJOR,
+};
+static Blt_CustomOption minorTicksOption = {
+ ObjToTicksProc, TicksToObjProc, FreeTicksProc, (ClientData)AXIS_AUTO_MINOR,
+};
+static Blt_OptionFreeProc FreeAxisProc;
+static Blt_OptionPrintProc AxisToObjProc;
+static Blt_OptionParseProc ObjToAxisProc;
+Blt_CustomOption bltXAxisOption = {
+ ObjToAxisProc, AxisToObjProc, FreeAxisProc, (ClientData)CID_AXIS_X
+};
+Blt_CustomOption bltYAxisOption = {
+ ObjToAxisProc, AxisToObjProc, FreeAxisProc, (ClientData)CID_AXIS_Y
+};
+
+static Blt_OptionFreeProc FreeFormatProc;
+static Blt_OptionParseProc ObjToFormatProc;
+static Blt_OptionPrintProc FormatToObjProc;
+static Blt_CustomOption formatOption = {
+ ObjToFormatProc, FormatToObjProc, FreeFormatProc, (ClientData)0,
+};
+static Blt_OptionParseProc ObjToLooseProc;
+static Blt_OptionPrintProc LooseToObjProc;
+static Blt_CustomOption looseOption = {
+ ObjToLooseProc, LooseToObjProc, NULL, (ClientData)0,
+};
+
+static Blt_OptionParseProc ObjToUseProc;
+static Blt_OptionPrintProc UseToObjProc;
+static Blt_CustomOption useOption = {
+ ObjToUseProc, UseToObjProc, NULL, (ClientData)0
+};
+
+#define DEF_AXIS_ACTIVEBACKGROUND STD_ACTIVE_BACKGROUND
+#define DEF_AXIS_ACTIVEFOREGROUND STD_ACTIVE_FOREGROUND
+#define DEF_AXIS_ACTIVERELIEF "flat"
+#define DEF_AXIS_ANGLE "0.0"
+#define DEF_AXIS_BACKGROUND (char *)NULL
+#define DEF_AXIS_BORDERWIDTH "0"
+#define DEF_AXIS_CHECKLIMITS "0"
+#define DEF_AXIS_COMMAND (char *)NULL
+#define DEF_AXIS_DESCENDING "0"
+#define DEF_AXIS_FOREGROUND RGB_BLACK
+#define DEF_AXIS_GRID_BARCHART "1"
+#define DEF_AXIS_GRIDCOLOR RGB_GREY64
+#define DEF_AXIS_GRIDDASHES "dot"
+#define DEF_AXIS_GRID_GRAPH "0"
+#define DEF_AXIS_GRIDLINEWIDTH "0"
+#define DEF_AXIS_GRIDMINOR "1"
+#define DEF_AXIS_GRIDMINOR_COLOR RGB_GREY64
+#define DEF_AXIS_HIDE "0"
+#define DEF_AXIS_JUSTIFY "c"
+#define DEF_AXIS_LIMITS_FORMAT (char *)NULL
+#define DEF_AXIS_LINEWIDTH "1"
+#define DEF_AXIS_LOGSCALE "0"
+#define DEF_AXIS_LOOSE "0"
+#define DEF_AXIS_RANGE "0.0"
+#define DEF_AXIS_RELIEF "flat"
+#define DEF_AXIS_SCROLL_INCREMENT "10"
+#define DEF_AXIS_SHIFTBY "0.0"
+#define DEF_AXIS_SHOWTICKS "1"
+#define DEF_AXIS_STEP "0.0"
+#define DEF_AXIS_STEP "0.0"
+#define DEF_AXIS_SUBDIVISIONS "2"
+#define DEF_AXIS_TAGS "all"
+#define DEF_AXIS_EXTERIOR "1"
+#define DEF_AXIS_TICK_ANCHOR "c"
+#define DEF_AXIS_LIMITS_FONT STD_FONT_NUMBERS
+#define DEF_AXIS_TICKFONT_GRAPH STD_FONT_NUMBERS
+#define DEF_AXIS_TICKFONT_BARCHART STD_FONT_SMALL
+#define DEF_AXIS_TICKLENGTH "4"
+#define DEF_AXIS_DIVISIONS "10"
+#define DEF_AXIS_TITLE_ALTERNATE "0"
+#define DEF_AXIS_TITLE_FG RGB_BLACK
+#define DEF_AXIS_TITLE_FONT "{Sans Serif} 10"
+#define DEF_AXIS_X_STEP_BARCHART "1.0"
+#define DEF_AXIS_X_SUBDIVISIONS_BARCHART "0"
+
+static Blt_ConfigSpec configSpecs[] =
+{
+ {BLT_CONFIG_BACKGROUND, "-activebackground", "activeBackground",
+ "ActiveBackground", DEF_AXIS_ACTIVEBACKGROUND,
+ Blt_Offset(Axis, activeBg), ALL_GRAPHS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground",
+ "ActiveForeground", DEF_AXIS_ACTIVEFOREGROUND,
+ Blt_Offset(Axis, activeFgColor), ALL_GRAPHS},
+ {BLT_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief",
+ DEF_AXIS_ACTIVERELIEF, Blt_Offset(Axis, activeRelief),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_DOUBLE, "-autorange", "autoRange", "AutoRange",
+ DEF_AXIS_RANGE, Blt_Offset(Axis, windowSize),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_AXIS_BACKGROUND, Blt_Offset(Axis, normalBg),
+ ALL_GRAPHS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_AXIS_TAGS,
+ Blt_Offset(Axis, obj.tags), ALL_GRAPHS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL,
+ 0, ALL_GRAPHS},
+ {BLT_CONFIG_PIXELS_NNEG, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_AXIS_BORDERWIDTH, Blt_Offset(Axis, borderWidth),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-checklimits", "checkLimits", "CheckLimits",
+ DEF_AXIS_CHECKLIMITS, Blt_Offset(Axis, flags),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)AXIS_CHECK_LIMITS},
+ {BLT_CONFIG_COLOR, "-color", "color", "Color",
+ DEF_AXIS_FOREGROUND, Blt_Offset(Axis, tickColor), ALL_GRAPHS},
+ {BLT_CONFIG_STRING, "-command", "command", "Command",
+ DEF_AXIS_COMMAND, Blt_Offset(Axis, formatCmd),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS},
+ {BLT_CONFIG_BOOLEAN, "-descending", "descending", "Descending",
+ DEF_AXIS_DESCENDING, Blt_Offset(Axis, descending),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-exterior", "exterior", "exterior", DEF_AXIS_EXTERIOR,
+ Blt_Offset(Axis, flags), ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)AXIS_EXTERIOR},
+ {BLT_CONFIG_SYNONYM, "-fg", "color", (char *)NULL,
+ (char *)NULL, 0, ALL_GRAPHS},
+ {BLT_CONFIG_SYNONYM, "-foreground", "color", (char *)NULL,
+ (char *)NULL, 0, ALL_GRAPHS},
+ {BLT_CONFIG_BITMASK, "-grid", "grid", "Grid", DEF_AXIS_GRID_BARCHART,
+ Blt_Offset(Axis, flags), BARCHART, (Blt_CustomOption *)AXIS_GRID},
+ {BLT_CONFIG_BITMASK, "-grid", "grid", "Grid", DEF_AXIS_GRID_GRAPH,
+ Blt_Offset(Axis, flags), GRAPH | STRIPCHART,
+ (Blt_CustomOption *)AXIS_GRID},
+ {BLT_CONFIG_COLOR, "-gridcolor", "gridColor", "GridColor",
+ DEF_AXIS_GRIDCOLOR, Blt_Offset(Axis, major.color), ALL_GRAPHS},
+ {BLT_CONFIG_DASHES, "-griddashes", "gridDashes", "GridDashes",
+ DEF_AXIS_GRIDDASHES, Blt_Offset(Axis, major.dashes),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS},
+ {BLT_CONFIG_PIXELS_NNEG, "-gridlinewidth", "gridLineWidth",
+ "GridLineWidth", DEF_AXIS_GRIDLINEWIDTH,
+ Blt_Offset(Axis, major.lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT | ALL_GRAPHS},
+ {BLT_CONFIG_BITMASK, "-gridminor", "gridMinor", "GridMinor",
+ DEF_AXIS_GRIDMINOR, Blt_Offset(Axis, flags),
+ BLT_CONFIG_DONT_SET_DEFAULT | ALL_GRAPHS,
+ (Blt_CustomOption *)AXIS_GRIDMINOR},
+ {BLT_CONFIG_COLOR, "-gridminorcolor", "gridMinorColor", "GridColor",
+ DEF_AXIS_GRIDMINOR_COLOR, Blt_Offset(Axis, minor.color), ALL_GRAPHS},
+ {BLT_CONFIG_DASHES, "-gridminordashes", "gridMinorDashes", "GridDashes",
+ DEF_AXIS_GRIDDASHES, Blt_Offset(Axis, minor.dashes),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS},
+ {BLT_CONFIG_PIXELS_NNEG, "-gridminorlinewidth", "gridMinorLineWidth",
+ "GridLineWidth", DEF_AXIS_GRIDLINEWIDTH,
+ Blt_Offset(Axis, minor.lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT | ALL_GRAPHS},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_AXIS_HIDE,
+ Blt_Offset(Axis, flags), ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_AXIS_JUSTIFY, Blt_Offset(Axis, titleJustify),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-labeloffset", "labelOffset", "LabelOffset",
+ (char *)NULL, Blt_Offset(Axis, labelOffset), ALL_GRAPHS},
+ {BLT_CONFIG_COLOR, "-limitscolor", "limitsColor", "Color",
+ DEF_AXIS_FOREGROUND, Blt_Offset(Axis, limitsTextStyle.color),
+ ALL_GRAPHS},
+ {BLT_CONFIG_FONT, "-limitsfont", "limitsFont", "Font", DEF_AXIS_LIMITS_FONT,
+ Blt_Offset(Axis, limitsTextStyle.font), ALL_GRAPHS},
+ {BLT_CONFIG_CUSTOM, "-limitsformat", "limitsFormat", "LimitsFormat",
+ (char *)NULL, Blt_Offset(Axis, limitsFormats),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS, &formatOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "LineWidth",
+ DEF_AXIS_LINEWIDTH, Blt_Offset(Axis, lineWidth),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-logscale", "logScale", "LogScale",
+ DEF_AXIS_LOGSCALE, Blt_Offset(Axis, logScale),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-loose", "loose", "Loose", DEF_AXIS_LOOSE, 0,
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT, &looseOption},
+ {BLT_CONFIG_CUSTOM, "-majorticks", "majorTicks", "MajorTicks",
+ (char *)NULL, Blt_Offset(Axis, t1Ptr),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS, &majorTicksOption},
+ {BLT_CONFIG_CUSTOM, "-max", "max", "Max", (char *)NULL,
+ Blt_Offset(Axis, reqMax), ALL_GRAPHS, &limitOption},
+ {BLT_CONFIG_CUSTOM, "-min", "min", "Min", (char *)NULL,
+ Blt_Offset(Axis, reqMin), ALL_GRAPHS, &limitOption},
+ {BLT_CONFIG_CUSTOM, "-minorticks", "minorTicks", "MinorTicks",
+ (char *)NULL, Blt_Offset(Axis, t2Ptr),
+ BLT_CONFIG_NULL_OK | ALL_GRAPHS, &minorTicksOption},
+ {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief",
+ DEF_AXIS_RELIEF, Blt_Offset(Axis, relief),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FLOAT, "-rotate", "rotate", "Rotate", DEF_AXIS_ANGLE,
+ Blt_Offset(Axis, tickAngle), ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_OBJ, "-scrollcommand", "scrollCommand", "ScrollCommand",
+ (char *)NULL, Blt_Offset(Axis, scrollCmdObjPtr),
+ ALL_GRAPHS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_POS, "-scrollincrement", "scrollIncrement",
+ "ScrollIncrement", DEF_AXIS_SCROLL_INCREMENT,
+ Blt_Offset(Axis, scrollUnits), ALL_GRAPHS|BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-scrollmax", "scrollMax", "ScrollMax", (char *)NULL,
+ Blt_Offset(Axis, reqScrollMax), ALL_GRAPHS, &limitOption},
+ {BLT_CONFIG_CUSTOM, "-scrollmin", "scrollMin", "ScrollMin", (char *)NULL,
+ Blt_Offset(Axis, reqScrollMin), ALL_GRAPHS, &limitOption},
+ {BLT_CONFIG_DOUBLE, "-shiftby", "shiftBy", "ShiftBy",
+ DEF_AXIS_SHIFTBY, Blt_Offset(Axis, shiftBy),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-showticks", "showTicks", "ShowTicks",
+ DEF_AXIS_SHOWTICKS, Blt_Offset(Axis, flags),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)AXIS_SHOWTICKS},
+ {BLT_CONFIG_DOUBLE, "-stepsize", "stepSize", "StepSize",
+ DEF_AXIS_STEP, Blt_Offset(Axis, reqStep),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_INT, "-subdivisions", "subdivisions", "Subdivisions",
+ DEF_AXIS_SUBDIVISIONS, Blt_Offset(Axis, reqNumMinorTicks), ALL_GRAPHS},
+ {BLT_CONFIG_ANCHOR, "-tickanchor", "tickAnchor", "Anchor",
+ DEF_AXIS_TICK_ANCHOR, Blt_Offset(Axis, reqTickAnchor), ALL_GRAPHS},
+ {BLT_CONFIG_FONT, "-tickfont", "tickFont", "Font",
+ DEF_AXIS_TICKFONT_GRAPH, Blt_Offset(Axis, tickFont),
+ GRAPH | STRIPCHART},
+ {BLT_CONFIG_FONT, "-tickfont", "tickFont", "Font",
+ DEF_AXIS_TICKFONT_BARCHART, Blt_Offset(Axis, tickFont), BARCHART},
+ {BLT_CONFIG_PIXELS_NNEG, "-ticklength", "tickLength", "TickLength",
+ DEF_AXIS_TICKLENGTH, Blt_Offset(Axis, tickLength),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_INT, "-tickdefault", "tickDefault", "TickDefault",
+ DEF_AXIS_DIVISIONS, Blt_Offset(Axis, reqNumMajorTicks),
+ ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-title", "title", "Title",
+ (char *)NULL, Blt_Offset(Axis, title),
+ BLT_CONFIG_DONT_SET_DEFAULT | BLT_CONFIG_NULL_OK | ALL_GRAPHS},
+ {BLT_CONFIG_BOOLEAN, "-titlealternate", "titleAlternate", "TitleAlternate",
+ DEF_AXIS_TITLE_ALTERNATE, Blt_Offset(Axis, titleAlternate),
+ BLT_CONFIG_DONT_SET_DEFAULT | ALL_GRAPHS},
+ {BLT_CONFIG_COLOR, "-titlecolor", "titleColor", "Color",
+ DEF_AXIS_FOREGROUND, Blt_Offset(Axis, titleColor),
+ ALL_GRAPHS},
+ {BLT_CONFIG_FONT, "-titlefont", "titleFont", "Font", DEF_AXIS_TITLE_FONT,
+ Blt_Offset(Axis, titleFont), ALL_GRAPHS},
+ {BLT_CONFIG_CUSTOM, "-use", "use", "Use", (char *)NULL, 0, ALL_GRAPHS,
+ &useOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+/* Forward declarations */
+static void DestroyAxis(Axis *axisPtr);
+static Tcl_FreeProc FreeAxis;
+static int GetAxisByClass(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ ClassId classId, Axis **axisPtrPtr);
+static void TimeScaleAxis(Axis *axisPtr, double min, double max);
+
+static int lastMargin;
+typedef int (GraphAxisProc)(Tcl_Interp *interp, Axis *axisPtr, int objc,
+ Tcl_Obj *const *objv);
+typedef int (GraphVirtualAxisProc)(Tcl_Interp *interp, Graph *graphPtr,
+ int objc, Tcl_Obj *const *objv);
+
+INLINE static double
+Clamp(double x)
+{
+ return (x < 0.0) ? 0.0 : (x > 1.0) ? 1.0 : x;
+}
+
+INLINE static int
+Round(double x)
+{
+ return (int) (x + ((x < 0.0) ? -0.5 : 0.5));
+}
+
+static void
+SetAxisRange(AxisRange *rangePtr, double min, double max)
+{
+ rangePtr->min = min;
+ rangePtr->max = max;
+ rangePtr->range = max - min;
+ if (fabs(rangePtr->range) < DBL_EPSILON) {
+ rangePtr->range = 1.0;
+ }
+ rangePtr->scale = 1.0 / rangePtr->range;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InRange --
+ *
+ * Determines if a value lies within a given range.
+ *
+ * The value is normalized and compared against the interval [0..1],
+ * where 0.0 is the minimum and 1.0 is the maximum. DBL_EPSILON is the
+ * smallest number that can be represented on the host machine, such that
+ * (1.0 + epsilon) != 1.0.
+ *
+ * Please note, *max* can't equal *min*.
+ *
+ * Results:
+ * If the value is within the interval [min..max], 1 is returned; 0
+ * otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+INLINE static int
+InRange(double x, AxisRange *rangePtr)
+{
+ if (rangePtr->range < DBL_EPSILON) {
+ return (fabs(rangePtr->max - x) >= DBL_EPSILON);
+ } else {
+ double norm;
+
+ norm = (x - rangePtr->min) * rangePtr->scale;
+ return ((norm >= -DBL_EPSILON) && ((norm - 1.0) < DBL_EPSILON));
+ }
+}
+
+INLINE static int
+AxisIsHorizontal(Axis *axisPtr)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ return ((axisPtr->obj.classId == CID_AXIS_Y) == graphPtr->inverted);
+}
+
+
+static void
+ReleaseAxis(Axis *axisPtr)
+{
+ if (axisPtr != NULL) {
+ axisPtr->refCount--;
+ assert(axisPtr->refCount >= 0);
+ if (axisPtr->refCount == 0) {
+ axisPtr->flags |= DELETE_PENDING;
+ Tcl_EventuallyFree(axisPtr, FreeAxis);
+ }
+ }
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ * Custom option parse and print procedures
+ *-----------------------------------------------------------------------------
+ */
+
+/*ARGSUSED*/
+static void
+FreeAxisProc(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Axis **axisPtrPtr = (Axis **)(widgRec + offset);
+
+ if (*axisPtrPtr != NULL) {
+ ReleaseAxis(*axisPtrPtr);
+ *axisPtrPtr = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToAxisProc --
+ *
+ * Converts the name of an axis to a pointer to its axis structure.
+ *
+ * Results:
+ * The return value is a standard TCL result. The axis flags are written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToAxisProc(
+ ClientData clientData, /* Class identifier of the type of
+ * axis we are looking for. */
+ Tcl_Interp *interp, /* Interpreter to report results. */
+ Tk_Window tkwin, /* Used to look up pointer to graph. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ ClassId classId = (ClassId)clientData;
+ Axis **axisPtrPtr = (Axis **)(widgRec + offset);
+ Axis *axisPtr;
+ Graph *graphPtr;
+
+ if (flags & BLT_CONFIG_NULL_OK) {
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ if (string[0] == '\0') {
+ ReleaseAxis(*axisPtrPtr);
+ *axisPtrPtr = NULL;
+ return TCL_OK;
+ }
+ }
+ graphPtr = Blt_GetGraphFromWindowData(tkwin);
+ assert(graphPtr);
+ if (GetAxisByClass(interp, graphPtr, objPtr, classId, &axisPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ReleaseAxis(*axisPtrPtr);
+ *axisPtrPtr = axisPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisToObjProc --
+ *
+ * Convert the window coordinates into a string.
+ *
+ * Results:
+ * The string representing the coordinate position is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+AxisToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Pointer to structure record .*/
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = *(Axis **)(widgRec + offset);
+ const char *name;
+
+ name = (axisPtr == NULL) ? "" : axisPtr->obj.name;
+ return Tcl_NewStringObj(name, -1);
+}
+
+/*ARGSUSED*/
+static void
+FreeFormatProc(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+
+ if (axisPtr->limitsFormats != NULL) {
+ free(axisPtr->limitsFormats);
+ axisPtr->limitsFormats = NULL;
+ }
+ axisPtr->nFormats = 0;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToFormatProc --
+ *
+ * Convert the name of virtual axis to an pointer.
+ *
+ * Results:
+ * The return value is a standard TCL result. The axis flags are written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToFormatProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to report results. */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+ const char **argv;
+ int argc;
+
+ if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &argc, &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (argc > 2) {
+ Tcl_AppendResult(interp, "too many elements in limits format list \"",
+ Tcl_GetString(objPtr), "\"", (char *)NULL);
+ free(argv);
+ return TCL_ERROR;
+ }
+ if (axisPtr->limitsFormats != NULL) {
+ free(axisPtr->limitsFormats);
+ }
+ axisPtr->limitsFormats = argv;
+ axisPtr->nFormats = argc;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FormatToObjProc --
+ *
+ * Convert the window coordinates into a string.
+ *
+ * Results:
+ * The string representing the coordinate position is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+FormatToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+ Tcl_Obj *objPtr;
+
+ if (axisPtr->nFormats == 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ } else {
+ char *string;
+
+ string = Tcl_Merge(axisPtr->nFormats, axisPtr->limitsFormats);
+ objPtr = Tcl_NewStringObj(string, -1);
+ free(string);
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToLimitProc --
+ *
+ * Convert the string representation of an axis limit into its numeric
+ * form.
+ *
+ * Results:
+ * The return value is a standard TCL result. The symbol type is written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToLimitProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ double *limitPtr = (double *)(widgRec + offset);
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ if (string[0] == '\0') {
+ *limitPtr = NAN;
+ } else if (Blt_ExprDoubleFromObj(interp, objPtr, limitPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LimitToObjProc --
+ *
+ * Convert the floating point axis limits into a string.
+ *
+ * Results:
+ * The string representation of the limits is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+LimitToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ double limit = *(double *)(widgRec + offset);
+ Tcl_Obj *objPtr;
+
+ if (isnormal(limit)) {
+ objPtr = Tcl_NewDoubleObj(limit);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToUseProc --
+ *
+ * Convert the string representation of the margin to use into its
+ * numeric form.
+ *
+ * Results:
+ * The return value is a standard TCL result. The use type is written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToUseProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results. */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+ AxisName *p, *pend;
+ Blt_Chain chain;
+ Graph *graphPtr;
+ const char *string;
+ int margin;
+
+ graphPtr = axisPtr->obj.graphPtr;
+ if (axisPtr->refCount == 0) {
+ /* Clear the axis class if it's not currently used by an element.*/
+ Blt_GraphSetObjectClass(&axisPtr->obj, CID_NONE);
+ }
+ /* Remove the axis from the margin's use list and clear its use flag. */
+ if (axisPtr->link != NULL) {
+ Blt_Chain_UnlinkLink(axisPtr->chain, axisPtr->link);
+ }
+ axisPtr->flags &= ~AXIS_USE;
+ string = Tcl_GetString(objPtr);
+ if ((string == NULL) || (string[0] == '\0')) {
+ goto done;
+ }
+ for (p = axisNames, pend = axisNames + nAxisNames; p < pend; p++) {
+ if (strcmp(p->name, string) == 0) {
+ break; /* Found the axis name. */
+ }
+ }
+ if (p == pend) {
+ Tcl_AppendResult(interp, "unknown axis type \"", string, "\": "
+ "should be x, y, x1, y2, or \"\".", (char *)NULL);
+ return TCL_ERROR;
+ }
+ /* Check the axis class. Can't use the axis if it's already being used as
+ * another type. */
+ if (axisPtr->obj.classId == CID_NONE) {
+ Blt_GraphSetObjectClass(&axisPtr->obj, p->classId);
+ } else if (axisPtr->obj.classId != p->classId) {
+ Tcl_AppendResult(interp, "wrong type for axis \"",
+ axisPtr->obj.name, "\": can't use ",
+ axisPtr->obj.className, " type axis.", (char *)NULL);
+ return TCL_ERROR;
+ }
+ margin = (graphPtr->inverted) ? p->invertMargin : p->margin;
+ chain = graphPtr->margins[margin].axes;
+ if (axisPtr->link != NULL) {
+ /* Move the axis from the old margin's "use" list to the new. */
+ Blt_Chain_AppendLink(chain, axisPtr->link);
+ } else {
+ axisPtr->link = Blt_Chain_Append(chain, axisPtr);
+ }
+ axisPtr->chain = chain;
+ axisPtr->flags |= AXIS_USE;
+ axisPtr->margin = margin;
+ done:
+ graphPtr->flags |= (GET_AXIS_GEOMETRY | LAYOUT_NEEDED | RESET_AXES);
+ /* When any axis changes, we need to layout the entire graph. */
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UseToObjProc --
+ *
+ * Convert the floating point axis limits into a string.
+ *
+ * Results:
+ * The string representation of the limits is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+UseToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+
+ if (axisPtr->margin == MARGIN_NONE) {
+ return Tcl_NewStringObj("", -1);
+ }
+ return Tcl_NewStringObj(axisNames[axisPtr->margin].name, -1);
+}
+
+/*ARGSUSED*/
+static void
+FreeTicksProc(
+ ClientData clientData, /* Either AXIS_AUTO_MAJOR or
+ * AXIS_AUTO_MINOR. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Axis *axisPtr = (Axis *)widgRec;
+ Ticks **ticksPtrPtr = (Ticks **) (widgRec + offset);
+ unsigned long mask = (unsigned long)clientData;
+
+ axisPtr->flags |= mask;
+ if (*ticksPtrPtr != NULL) {
+ free(*ticksPtrPtr);
+ }
+ *ticksPtrPtr = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToTicksProc --
+ *
+ *
+ * Results:
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToTicksProc(
+ ClientData clientData, /* Either AXIS_AUTO_MAJOR or
+ * AXIS_AUTO_MINOR. */
+ Tcl_Interp *interp, /* Interpreter to send results. */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)widgRec;
+ Tcl_Obj **objv;
+ Ticks **ticksPtrPtr = (Ticks **) (widgRec + offset);
+ Ticks *ticksPtr;
+ int objc;
+ unsigned long mask = (unsigned long)clientData;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ axisPtr->flags |= mask;
+ ticksPtr = NULL;
+ if (objc > 0) {
+ int i;
+
+ ticksPtr = malloc(sizeof(Ticks) + (objc*sizeof(double)));
+ for (i = 0; i < objc; i++) {
+ double value;
+
+ if (Blt_ExprDoubleFromObj(interp, objv[i], &value) != TCL_OK) {
+ free(ticksPtr);
+ return TCL_ERROR;
+ }
+ ticksPtr->values[i] = value;
+ }
+ ticksPtr->nTicks = objc;
+ axisPtr->flags &= ~mask;
+ }
+ FreeTicksProc(clientData, Tk_Display(tkwin), widgRec, offset);
+ *ticksPtrPtr = ticksPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TicksToObjProc --
+ *
+ * Convert array of tick coordinates to a list.
+ *
+ * Results:
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+TicksToObjProc(
+ ClientData clientData, /* Either AXIS_AUTO_MAJOR or
+ * AXIS_AUTO_MINOR. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr;
+ Tcl_Obj *listObjPtr;
+ Ticks *ticksPtr;
+ unsigned long mask;
+
+ axisPtr = (Axis *)widgRec;
+ ticksPtr = *(Ticks **) (widgRec + offset);
+ mask = (unsigned long)clientData;
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if ((ticksPtr != NULL) && ((axisPtr->flags & mask) == 0)) {
+ unsigned int i;
+
+ for (i = 0; i < ticksPtr->nTicks; i++) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewDoubleObj(ticksPtr->values[i]);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ }
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToLooseProc --
+ *
+ * Convert a string to one of three values.
+ * 0 - false, no, off
+ * 1 - true, yes, on
+ * 2 - always
+ * Results:
+ * If the string is successfully converted, TCL_OK is returned.
+ * Otherwise, TCL_ERROR is returned and an error message is left in
+ * interpreter's result field.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToLooseProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results. */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing new value. */
+ char *widgRec, /* Pointer to structure record. */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)(widgRec);
+ Tcl_Obj **objv;
+ int i;
+ int objc;
+ int values[2];
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc < 1) || (objc > 2)) {
+ Tcl_AppendResult(interp, "wrong # elements in loose value \"",
+ Tcl_GetString(objPtr), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ const char *string;
+
+ string = Tcl_GetString(objv[i]);
+ if ((string[0] == 'a') && (strcmp(string, "always") == 0)) {
+ values[i] = AXIS_ALWAYS_LOOSE;
+ } else {
+ int bool;
+
+ if (Tcl_GetBooleanFromObj(interp, objv[i], &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ values[i] = bool;
+ }
+ }
+ axisPtr->looseMin = axisPtr->looseMax = values[0];
+ if (objc > 1) {
+ axisPtr->looseMax = values[1];
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LooseToObjProc --
+ *
+ * Results:
+ * The string representation of the auto boolean is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+LooseToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Axis *axisPtr = (Axis *)widgRec;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (axisPtr->looseMin == AXIS_TIGHT) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewBooleanObj(FALSE));
+ } else if (axisPtr->looseMin == AXIS_LOOSE) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewBooleanObj(TRUE));
+ } else if (axisPtr->looseMin == AXIS_ALWAYS_LOOSE) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("always", 6));
+ }
+ if (axisPtr->looseMin != axisPtr->looseMax) {
+ if (axisPtr->looseMax == AXIS_TIGHT) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewBooleanObj(FALSE));
+ } else if (axisPtr->looseMax == AXIS_LOOSE) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewBooleanObj(TRUE));
+ } else if (axisPtr->looseMax == AXIS_ALWAYS_LOOSE) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("always", 6));
+ }
+ }
+ return listObjPtr;
+}
+
+static void
+FreeTickLabels(Blt_Chain chain)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ TickLabel *labelPtr;
+
+ labelPtr = Blt_Chain_GetValue(link);
+ free(labelPtr);
+ }
+ Blt_Chain_Reset(chain);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MakeLabel --
+ *
+ * Converts a floating point tick value to a string to be used as its
+ * label.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Returns a new label in the string character buffer. The formatted
+ * tick label will be displayed on the graph.
+ *
+ * --------------------------------------------------------------------------
+ */
+static TickLabel *
+MakeLabel(Axis *axisPtr, double value)
+{
+#define TICK_LABEL_SIZE 200
+ char string[TICK_LABEL_SIZE + 1];
+ TickLabel *labelPtr;
+
+ /* Generate a default tick label based upon the tick value. */
+ if (axisPtr->logScale) {
+ sprintf_s(string, TICK_LABEL_SIZE, "1E%d", ROUND(value));
+ } else {
+ sprintf_s(string, TICK_LABEL_SIZE, "%.*G", NUMDIGITS, value);
+ }
+
+ if (axisPtr->formatCmd != NULL) {
+ Graph *graphPtr;
+ Tcl_Interp *interp;
+ Tk_Window tkwin;
+
+ graphPtr = axisPtr->obj.graphPtr;
+ interp = graphPtr->interp;
+ tkwin = graphPtr->tkwin;
+ /*
+ * A TCL proc was designated to format tick labels. Append the path
+ * name of the widget and the default tick label as arguments when
+ * invoking it. Copy and save the new label from interp->result.
+ */
+ Tcl_ResetResult(interp);
+ if (Tcl_VarEval(interp, axisPtr->formatCmd, " ", Tk_PathName(tkwin),
+ " ", string, (char *)NULL) != TCL_OK) {
+ Tcl_BackgroundError(interp);
+ } else {
+ /*
+ * The proc could return a string of any length, so arbitrarily
+ * limit it to what will fit in the return string.
+ */
+ strncpy(string, Tcl_GetStringResult(interp), TICK_LABEL_SIZE);
+ string[TICK_LABEL_SIZE] = '\0';
+
+ Tcl_ResetResult(interp); /* Clear the interpreter's result. */
+ }
+ }
+ labelPtr = malloc(sizeof(TickLabel) + strlen(string));
+ strcpy(labelPtr->string, string);
+ labelPtr->anchorPos.x = labelPtr->anchorPos.y = DBL_MAX;
+ return labelPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InvHMap --
+ *
+ * Maps the given screen coordinate back to a graph coordinate. Called
+ * by the graph locater routine.
+ *
+ * Results:
+ * Returns the graph coordinate value at the given window
+ * y-coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+double
+Blt_InvHMap(Axis *axisPtr, double x)
+{
+ double value;
+
+ x = (double)(x - axisPtr->screenMin) * axisPtr->screenScale;
+ if (axisPtr->descending) {
+ x = 1.0 - x;
+ }
+ value = (x * axisPtr->axisRange.range) + axisPtr->axisRange.min;
+ if (axisPtr->logScale) {
+ value = EXP10(value);
+ }
+ return value;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InvVMap --
+ *
+ * Maps the given screen y-coordinate back to the graph coordinate
+ * value. Called by the graph locater routine.
+ *
+ * Results:
+ * Returns the graph coordinate value for the given screen
+ * coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+double
+Blt_InvVMap(Axis *axisPtr, double y) /* Screen coordinate */
+{
+ double value;
+
+ y = (double)(y - axisPtr->screenMin) * axisPtr->screenScale;
+ if (axisPtr->descending) {
+ y = 1.0 - y;
+ }
+ value = ((1.0 - y) * axisPtr->axisRange.range) + axisPtr->axisRange.min;
+ if (axisPtr->logScale) {
+ value = EXP10(value);
+ }
+ return value;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_HMap --
+ *
+ * Map the given graph coordinate value to its axis, returning a window
+ * position.
+ *
+ * Results:
+ * Returns a double precision number representing the window coordinate
+ * position on the given axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+double
+Blt_HMap(Axis *axisPtr, double x)
+{
+ if ((axisPtr->logScale) && (x != 0.0)) {
+ x = log10(fabs(x));
+ }
+ /* Map graph coordinate to normalized coordinates [0..1] */
+ x = (x - axisPtr->axisRange.min) * axisPtr->axisRange.scale;
+ if (axisPtr->descending) {
+ x = 1.0 - x;
+ }
+ return (x * axisPtr->screenRange + axisPtr->screenMin);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_VMap --
+ *
+ * Map the given graph coordinate value to its axis, returning a window
+ * position.
+ *
+ * Results:
+ * Returns a double precision number representing the window coordinate
+ * position on the given axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+double
+Blt_VMap(Axis *axisPtr, double y)
+{
+ if ((axisPtr->logScale) && (y != 0.0)) {
+ y = log10(fabs(y));
+ }
+ /* Map graph coordinate to normalized coordinates [0..1] */
+ y = (y - axisPtr->axisRange.min) * axisPtr->axisRange.scale;
+ if (axisPtr->descending) {
+ y = 1.0 - y;
+ }
+ return ((1.0 - y) * axisPtr->screenRange + axisPtr->screenMin);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Map2D --
+ *
+ * Maps the given graph x,y coordinate values to a window position.
+ *
+ * Results:
+ * Returns a XPoint structure containing the window coordinates of
+ * the given graph x,y coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+Point2d
+Blt_Map2D(
+ Graph *graphPtr,
+ double x, double y, /* Graph x and y coordinates */
+ Axis2d *axesPtr) /* Specifies which axes to use */
+{
+ Point2d point;
+
+ if (graphPtr->inverted) {
+ point.x = Blt_HMap(axesPtr->y, y);
+ point.y = Blt_VMap(axesPtr->x, x);
+ } else {
+ point.x = Blt_HMap(axesPtr->x, x);
+ point.y = Blt_VMap(axesPtr->y, y);
+ }
+ return point;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InvMap2D --
+ *
+ * Maps the given window x,y coordinates to graph values.
+ *
+ * Results:
+ * Returns a structure containing the graph coordinates of the given
+ * window x,y coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+Point2d
+Blt_InvMap2D(
+ Graph *graphPtr,
+ double x, double y, /* Window x and y coordinates */
+ Axis2d *axesPtr) /* Specifies which axes to use */
+{
+ Point2d point;
+
+ if (graphPtr->inverted) {
+ point.x = Blt_InvVMap(axesPtr->x, y);
+ point.y = Blt_InvHMap(axesPtr->y, x);
+ } else {
+ point.x = Blt_InvHMap(axesPtr->x, x);
+ point.y = Blt_InvVMap(axesPtr->y, y);
+ }
+ return point;
+}
+
+
+static void
+GetDataLimits(Axis *axisPtr, double min, double max)
+{
+ if (axisPtr->valueRange.min > min) {
+ axisPtr->valueRange.min = min;
+ }
+ if (axisPtr->valueRange.max < max) {
+ axisPtr->valueRange.max = max;
+ }
+}
+
+static void
+FixAxisRange(Axis *axisPtr)
+{
+ double min, max;
+
+ /*
+ * When auto-scaling, the axis limits are the bounds of the element data.
+ * If no data exists, set arbitrary limits (wrt to log/linear scale).
+ */
+ min = axisPtr->valueRange.min;
+ max = axisPtr->valueRange.max;
+
+ /* Check the requested axis limits. Can't allow -min to be greater
+ * than -max, or have undefined log scale limits. */
+ if (((isnormal(axisPtr->reqMin)) && (isnormal(axisPtr->reqMax))) &&
+ (axisPtr->reqMin >= axisPtr->reqMax)) {
+ axisPtr->reqMin = axisPtr->reqMax = NAN;
+ }
+ if (axisPtr->logScale) {
+ if ((isnormal(axisPtr->reqMin)) && (axisPtr->reqMin <= 0.0)) {
+ axisPtr->reqMin = NAN;
+ }
+ if ((isnormal(axisPtr->reqMax)) && (axisPtr->reqMax <= 0.0)) {
+ axisPtr->reqMax = NAN;
+ }
+ }
+
+ if (min == DBL_MAX) {
+ if (isnormal(axisPtr->reqMin)) {
+ min = axisPtr->reqMin;
+ } else {
+ min = (axisPtr->logScale) ? 0.001 : 0.0;
+ }
+ }
+ if (max == -DBL_MAX) {
+ if (isnormal(axisPtr->reqMax)) {
+ max = axisPtr->reqMax;
+ } else {
+ max = 1.0;
+ }
+ }
+ if (min >= max) {
+ /*
+ * There is no range of data (i.e. min is not less than max), so
+ * manufacture one.
+ */
+ if (min == 0.0) {
+ min = 0.0, max = 1.0;
+ } else {
+ max = min + (fabs(min) * 0.1);
+ }
+ }
+ SetAxisRange(&axisPtr->valueRange, min, max);
+
+ /*
+ * The axis limits are either the current data range or overridden by the
+ * values selected by the user with the -min or -max options.
+ */
+ axisPtr->min = min;
+ axisPtr->max = max;
+ if (isnormal(axisPtr->reqMin)) {
+ axisPtr->min = axisPtr->reqMin;
+ }
+ if (isnormal(axisPtr->reqMax)) {
+ axisPtr->max = axisPtr->reqMax;
+ }
+ if (axisPtr->max < axisPtr->min) {
+ /*
+ * If the limits still don't make sense, it's because one limit
+ * configuration option (-min or -max) was set and the other default
+ * (based upon the data) is too small or large. Remedy this by making
+ * up a new min or max from the user-defined limit.
+ */
+ if (!isnormal(axisPtr->reqMin)) {
+ axisPtr->min = axisPtr->max - (fabs(axisPtr->max) * 0.1);
+ }
+ if (!isnormal(axisPtr->reqMax)) {
+ axisPtr->max = axisPtr->min + (fabs(axisPtr->max) * 0.1);
+ }
+ }
+ /*
+ * If a window size is defined, handle auto ranging by shifting the axis
+ * limits.
+ */
+ if ((axisPtr->windowSize > 0.0) &&
+ (!isnormal(axisPtr->reqMin)) && (!isnormal(axisPtr->reqMax))) {
+ if (axisPtr->shiftBy < 0.0) {
+ axisPtr->shiftBy = 0.0;
+ }
+ max = axisPtr->min + axisPtr->windowSize;
+ if (axisPtr->max >= max) {
+ if (axisPtr->shiftBy > 0.0) {
+ max = UCEIL(axisPtr->max, axisPtr->shiftBy);
+ }
+ axisPtr->min = max - axisPtr->windowSize;
+ }
+ axisPtr->max = max;
+ }
+ if ((axisPtr->max != axisPtr->prevMax) ||
+ (axisPtr->min != axisPtr->prevMin)) {
+ /* Indicate if the axis limits have changed */
+ axisPtr->flags |= DIRTY;
+ /* and save the previous minimum and maximum values */
+ axisPtr->prevMin = axisPtr->min;
+ axisPtr->prevMax = axisPtr->max;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NiceNum --
+ *
+ * Reference: Paul Heckbert, "Nice Numbers for Graph Labels",
+ * Graphics Gems, pp 61-63.
+ *
+ * Finds a "nice" number approximately equal to x.
+ *
+ *---------------------------------------------------------------------------
+ */
+static double
+NiceNum(double x, int round) /* If non-zero, round. Otherwise take
+ * ceiling of value. */
+{
+ double expt; /* Exponent of x */
+ double frac; /* Fractional part of x */
+ double nice; /* Nice, rounded fraction */
+
+ expt = floor(log10(x));
+ frac = x / EXP10(expt); /* between 1 and 10 */
+ if (round) {
+ if (frac < 1.5) {
+ nice = 1.0;
+ } else if (frac < 3.0) {
+ nice = 2.0;
+ } else if (frac < 7.0) {
+ nice = 5.0;
+ } else {
+ nice = 10.0;
+ }
+ } else {
+ if (frac <= 1.0) {
+ nice = 1.0;
+ } else if (frac <= 2.0) {
+ nice = 2.0;
+ } else if (frac <= 5.0) {
+ nice = 5.0;
+ } else {
+ nice = 10.0;
+ }
+ }
+ return nice * EXP10(expt);
+}
+
+static Ticks *
+GenerateTicks(TickSweep *sweepPtr)
+{
+ Ticks *ticksPtr;
+
+ ticksPtr = malloc(sizeof(Ticks) +
+ (sweepPtr->nSteps * sizeof(double)));
+ ticksPtr->nTicks = 0;
+
+ if (sweepPtr->step == 0.0) {
+ /* Hack: A zero step indicates to use log values. */
+ int i;
+ /* Precomputed log10 values [1..10] */
+ static double logTable[] = {
+ 0.0,
+ 0.301029995663981,
+ 0.477121254719662,
+ 0.602059991327962,
+ 0.698970004336019,
+ 0.778151250383644,
+ 0.845098040014257,
+ 0.903089986991944,
+ 0.954242509439325,
+ 1.0
+ };
+ for (i = 0; i < sweepPtr->nSteps; i++) {
+ ticksPtr->values[i] = logTable[i];
+ }
+ } else {
+ double value;
+ int i;
+
+ value = sweepPtr->initial; /* Start from smallest axis tick */
+ for (i = 0; i < sweepPtr->nSteps; i++) {
+ value = UROUND(value, sweepPtr->step);
+ ticksPtr->values[i] = value;
+ value += sweepPtr->step;
+ }
+ }
+ ticksPtr->nTicks = sweepPtr->nSteps;
+ return ticksPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LogScaleAxis --
+ *
+ * Determine the range and units of a log scaled axis.
+ *
+ * Unless the axis limits are specified, the axis is scaled
+ * automatically, where the smallest and largest major ticks encompass
+ * the range of actual data values. When an axis limit is specified,
+ * that value represents the smallest(min)/largest(max) value in the
+ * displayed range of values.
+ *
+ * Both manual and automatic scaling are affected by the step used. By
+ * default, the step is the largest power of ten to divide the range in
+ * more than one piece.
+ *
+ * Automatic scaling:
+ * Find the smallest number of units which contain the range of values.
+ * The minimum and maximum major tick values will be represent the
+ * range of values for the axis. This greatest number of major ticks
+ * possible is 10.
+ *
+ * Manual scaling:
+ * Make the minimum and maximum data values the represent the range of
+ * the values for the axis. The minimum and maximum major ticks will be
+ * inclusive of this range. This provides the largest area for plotting
+ * and the expected results when the axis min and max values have be set
+ * by the user (.e.g zooming). The maximum number of major ticks is 20.
+ *
+ * For log scale, there's the possibility that the minimum and
+ * maximum data values are the same magnitude. To represent the
+ * points properly, at least one full decade should be shown.
+ * However, if you zoom a log scale plot, the results should be
+ * predictable. Therefore, in that case, show only minor ticks.
+ * Lastly, there should be an appropriate way to handle numbers
+ * <=0.
+ *
+ * maxY
+ * | units = magnitude (of least significant digit)
+ * | high = largest unit tick < max axis value
+ * high _| low = smallest unit tick > min axis value
+ * |
+ * | range = high - low
+ * | # ticks = greatest factor of range/units
+ * _|
+ * U |
+ * n |
+ * i |
+ * t _|
+ * |
+ * |
+ * |
+ * low _|
+ * |
+ * |_minX________________maxX__
+ * | | | | |
+ * minY low high
+ * minY
+ *
+ *
+ * numTicks = Number of ticks
+ * min = Minimum value of axis
+ * max = Maximum value of axis
+ * range = Range of values (max - min)
+ *
+ * If the number of decades is greater than ten, it is assumed
+ * that the full set of log-style ticks can't be drawn properly.
+ *
+ * Results:
+ * None
+ *
+ * -------------------------------------------------------------------------- */
+static void
+LogScaleAxis(Axis *axisPtr, double min, double max)
+{
+ double range;
+ double tickMin, tickMax;
+ double majorStep, minorStep;
+ int nMajor, nMinor;
+
+ nMajor = nMinor = 0;
+ /* Suppress compiler warnings. */
+ majorStep = minorStep = 0.0;
+ tickMin = tickMax = NAN;
+ if (min < max) {
+ min = (min != 0.0) ? log10(fabs(min)) : 0.0;
+ max = (max != 0.0) ? log10(fabs(max)) : 1.0;
+
+ tickMin = floor(min);
+ tickMax = ceil(max);
+ range = tickMax - tickMin;
+
+ if (range > 10) {
+ /* There are too many decades to display a major tick at every
+ * decade. Instead, treat the axis as a linear scale. */
+ range = NiceNum(range, 0);
+ majorStep = NiceNum(range / axisPtr->reqNumMajorTicks, 1);
+ tickMin = UFLOOR(tickMin, majorStep);
+ tickMax = UCEIL(tickMax, majorStep);
+ nMajor = (int)((tickMax - tickMin) / majorStep) + 1;
+ minorStep = EXP10(floor(log10(majorStep)));
+ if (minorStep == majorStep) {
+ nMinor = 4, minorStep = 0.2;
+ } else {
+ nMinor = Round(majorStep / minorStep) - 1;
+ }
+ } else {
+ if (tickMin == tickMax) {
+ tickMax++;
+ }
+ majorStep = 1.0;
+ nMajor = (int)(tickMax - tickMin + 1); /* FIXME: Check this. */
+
+ minorStep = 0.0; /* This is a special hack to pass
+ * information to the GenerateTicks
+ * routine. An interval of 0.0 tells 1)
+ * this is a minor sweep and 2) the axis
+ * is log scale. */
+ nMinor = 10;
+ }
+ if ((axisPtr->looseMin == AXIS_TIGHT) ||
+ ((axisPtr->looseMin == AXIS_LOOSE) &&
+ (isnormal(axisPtr->reqMin)))) {
+ tickMin = min;
+ nMajor++;
+ }
+ if ((axisPtr->looseMax == AXIS_TIGHT) ||
+ ((axisPtr->looseMax == AXIS_LOOSE) &&
+ (isnormal(axisPtr->reqMax)))) {
+ tickMax = max;
+ }
+ }
+ axisPtr->majorSweep.step = majorStep;
+ axisPtr->majorSweep.initial = floor(tickMin);
+ axisPtr->majorSweep.nSteps = nMajor;
+ axisPtr->minorSweep.initial = axisPtr->minorSweep.step = minorStep;
+ axisPtr->minorSweep.nSteps = nMinor;
+
+ SetAxisRange(&axisPtr->axisRange, tickMin, tickMax);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LinearScaleAxis --
+ *
+ * Determine the units of a linear scaled axis.
+ *
+ * The axis limits are either the range of the data values mapped
+ * to the axis (autoscaled), or the values specified by the -min
+ * and -max options (manual).
+ *
+ * If autoscaled, the smallest and largest major ticks will
+ * encompass the range of data values. If the -loose option is
+ * selected, the next outer ticks are choosen. If tight, the
+ * ticks are at or inside of the data limits are used.
+ *
+ * If manually set, the ticks are at or inside the data limits
+ * are used. This makes sense for zooming. You want the
+ * selected range to represent the next limit, not something a
+ * bit bigger.
+ *
+ * Note: I added an "always" value to the -loose option to force
+ * the manually selected axes to be loose. It's probably
+ * not a good idea.
+ *
+ * maxY
+ * | units = magnitude (of least significant digit)
+ * | high = largest unit tick < max axis value
+ * high _| low = smallest unit tick > min axis value
+ * |
+ * | range = high - low
+ * | # ticks = greatest factor of range/units
+ * _|
+ * U |
+ * n |
+ * i |
+ * t _|
+ * |
+ * |
+ * |
+ * low _|
+ * |
+ * |_minX________________maxX__
+ * | | | | |
+ * minY low high
+ * minY
+ *
+ * numTicks = Number of ticks
+ * min = Minimum value of axis
+ * max = Maximum value of axis
+ * range = Range of values (max - min)
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The axis tick information is set. The actual tick values will
+ * be generated later.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+LinearScaleAxis(Axis *axisPtr, double min, double max)
+{
+ double step;
+ double tickMin, tickMax;
+ double axisMin, axisMax;
+ unsigned int nTicks;
+
+ nTicks = 0;
+ step = 1.0;
+ /* Suppress compiler warning. */
+ axisMin = axisMax = tickMin = tickMax = NAN;
+ if (min < max) {
+ double range;
+
+ range = max - min;
+ /* Calculate the major tick stepping. */
+ if (axisPtr->reqStep > 0.0) {
+ /* An interval was designated by the user. Keep scaling it until
+ * it fits comfortably within the current range of the axis. */
+ step = axisPtr->reqStep;
+ while ((2 * step) >= range) {
+ step *= 0.5;
+ }
+ } else {
+ range = NiceNum(range, 0);
+ step = NiceNum(range / axisPtr->reqNumMajorTicks, 1);
+ }
+
+ /* Find the outer tick values. Add 0.0 to prevent getting -0.0. */
+ axisMin = tickMin = floor(min / step) * step + 0.0;
+ axisMax = tickMax = ceil(max / step) * step + 0.0;
+
+ nTicks = Round((tickMax - tickMin) / step) + 1;
+ }
+ axisPtr->majorSweep.step = step;
+ axisPtr->majorSweep.initial = tickMin;
+ axisPtr->majorSweep.nSteps = nTicks;
+
+ /*
+ * The limits of the axis are either the range of the data ("tight") or at
+ * the next outer tick interval ("loose"). The looseness or tightness has
+ * to do with how the axis fits the range of data values. This option is
+ * overridden when the user sets an axis limit (by either -min or -max
+ * option). The axis limit is always at the selected limit (otherwise we
+ * assume that user would have picked a different number).
+ */
+ if ((axisPtr->looseMin == AXIS_TIGHT) ||
+ ((axisPtr->looseMin == AXIS_LOOSE) &&
+ (isnormal(axisPtr->reqMin)))) {
+ axisMin = min;
+ }
+ if ((axisPtr->looseMax == AXIS_TIGHT) ||
+ ((axisPtr->looseMax == AXIS_LOOSE) &&
+ (isnormal(axisPtr->reqMax)))) {
+ axisMax = max;
+ }
+ SetAxisRange(&axisPtr->axisRange, axisMin, axisMax);
+
+ /* Now calculate the minor tick step and number. */
+
+ if ((axisPtr->reqNumMinorTicks > 0) && (axisPtr->flags & AXIS_AUTO_MAJOR)) {
+ nTicks = axisPtr->reqNumMinorTicks - 1;
+ step = 1.0 / (nTicks + 1);
+ } else {
+ nTicks = 0; /* No minor ticks. */
+ step = 0.5; /* Don't set the minor tick interval to
+ * 0.0. It makes the GenerateTicks
+ * routine * create minor log-scale tick
+ * marks. */
+ }
+ axisPtr->minorSweep.initial = axisPtr->minorSweep.step = step;
+ axisPtr->minorSweep.nSteps = nTicks;
+}
+
+
+static void
+SweepTicks(Axis *axisPtr)
+{
+ if (axisPtr->flags & AXIS_AUTO_MAJOR) {
+ if (axisPtr->t1Ptr != NULL) {
+ free(axisPtr->t1Ptr);
+ }
+ axisPtr->t1Ptr = GenerateTicks(&axisPtr->majorSweep);
+ }
+ if (axisPtr->flags & AXIS_AUTO_MINOR) {
+ if (axisPtr->t2Ptr != NULL) {
+ free(axisPtr->t2Ptr);
+ }
+ axisPtr->t2Ptr = GenerateTicks(&axisPtr->minorSweep);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ResetAxes --
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ResetAxes(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ /* FIXME: This should be called whenever the display list of
+ * elements change. Maybe yet another flag INIT_STACKS to
+ * indicate that the element display list has changed.
+ * Needs to be done before the axis limits are set.
+ */
+ Blt_InitBarSetTable(graphPtr);
+ if ((graphPtr->mode == BARS_STACKED) && (graphPtr->nBarGroups > 0)) {
+ Blt_ComputeBarStacks(graphPtr);
+ }
+ /*
+ * Step 1: Reset all axes. Initialize the data limits of the axis to
+ * impossible values.
+ */
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ axisPtr->min = axisPtr->valueRange.min = DBL_MAX;
+ axisPtr->max = axisPtr->valueRange.max = -DBL_MAX;
+ }
+
+ /*
+ * Step 2: For each element that's to be displayed, get the smallest
+ * and largest data values mapped to each X and Y-axis. This
+ * will be the axis limits if the user doesn't override them
+ * with -min and -max options.
+ */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ Region2d exts;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((graphPtr->flags & UNMAP_HIDDEN) && (elemPtr->flags & HIDE)) {
+ continue;
+ }
+ (*elemPtr->procsPtr->extentsProc) (elemPtr, &exts);
+ GetDataLimits(elemPtr->axes.x, exts.left, exts.right);
+ GetDataLimits(elemPtr->axes.y, exts.top, exts.bottom);
+ }
+ /*
+ * Step 3: Now that we know the range of data values for each axis,
+ * set axis limits and compute a sweep to generate tick values.
+ */
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+ double min, max;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ FixAxisRange(axisPtr);
+
+ /* Calculate min/max tick (major/minor) layouts */
+ min = axisPtr->min;
+ max = axisPtr->max;
+ if ((isnormal(axisPtr->scrollMin)) && (min < axisPtr->scrollMin)) {
+ min = axisPtr->scrollMin;
+ }
+ if ((isnormal(axisPtr->scrollMax)) && (max > axisPtr->scrollMax)) {
+ max = axisPtr->scrollMax;
+ }
+ if (axisPtr->logScale) {
+ LogScaleAxis(axisPtr, min, max);
+ } else if (axisPtr->timeScale) {
+ TimeScaleAxis(axisPtr, min, max);
+ } else {
+ LinearScaleAxis(axisPtr, min, max);
+ }
+
+ if ((axisPtr->flags & (DIRTY|AXIS_USE)) == (DIRTY|AXIS_USE)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ }
+
+ graphPtr->flags &= ~RESET_AXES;
+
+ /*
+ * When any axis changes, we need to layout the entire graph.
+ */
+ graphPtr->flags |= (GET_AXIS_GEOMETRY | LAYOUT_NEEDED | MAP_ALL |
+ REDRAW_WORLD);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ResetTextStyles --
+ *
+ * Configures axis attributes (font, line width, label, etc) and
+ * allocates a new (possibly shared) graphics context. Line cap style is
+ * projecting. This is for the problem of when a tick sits directly at
+ * the end point of the axis.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ * Axis resources are allocated (GC, font). Axis layout is deferred until
+ * the height and width of the window are known.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ResetTextStyles(Axis *axisPtr)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+
+ Blt_Ts_ResetStyle(graphPtr->tkwin, &axisPtr->limitsTextStyle);
+
+ gcMask = (GCForeground | GCLineWidth | GCCapStyle);
+ gcValues.foreground = axisPtr->tickColor->pixel;
+ gcValues.font = Blt_FontId(axisPtr->tickFont);
+ gcValues.line_width = LineWidth(axisPtr->lineWidth);
+ gcValues.cap_style = CapProjecting;
+
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (axisPtr->tickGC != NULL) {
+ Tk_FreeGC(graphPtr->display, axisPtr->tickGC);
+ }
+ axisPtr->tickGC = newGC;
+
+ /* Assuming settings from above GC */
+ gcValues.foreground = axisPtr->activeFgColor->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (axisPtr->activeTickGC != NULL) {
+ Tk_FreeGC(graphPtr->display, axisPtr->activeTickGC);
+ }
+ axisPtr->activeTickGC = newGC;
+
+ gcValues.background = gcValues.foreground = axisPtr->major.color->pixel;
+ gcValues.line_width = LineWidth(axisPtr->major.lineWidth);
+ gcMask = (GCForeground | GCBackground | GCLineWidth);
+ if (LineIsDashed(axisPtr->major.dashes)) {
+ gcValues.line_style = LineOnOffDash;
+ gcMask |= GCLineStyle;
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(axisPtr->major.dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &axisPtr->major.dashes);
+ }
+ if (axisPtr->major.gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, axisPtr->major.gc);
+ }
+ axisPtr->major.gc = newGC;
+
+ gcValues.background = gcValues.foreground = axisPtr->minor.color->pixel;
+ gcValues.line_width = LineWidth(axisPtr->minor.lineWidth);
+ gcMask = (GCForeground | GCBackground | GCLineWidth);
+ if (LineIsDashed(axisPtr->minor.dashes)) {
+ gcValues.line_style = LineOnOffDash;
+ gcMask |= GCLineStyle;
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(axisPtr->minor.dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &axisPtr->minor.dashes);
+ }
+ if (axisPtr->minor.gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, axisPtr->minor.gc);
+ }
+ axisPtr->minor.gc = newGC;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyAxis --
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources (font, color, gc, labels, etc.) associated with the axis are
+ * deallocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DestroyAxis(Axis *axisPtr)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ int flags;
+
+ flags = Blt_GraphType(graphPtr);
+ Blt_FreeOptions(configSpecs, (char *)axisPtr, graphPtr->display, flags);
+ if (graphPtr->bindTable != NULL) {
+ Blt_DeleteBindings(graphPtr->bindTable, axisPtr);
+ }
+ if (axisPtr->link != NULL) {
+ Blt_Chain_DeleteLink(axisPtr->chain, axisPtr->link);
+ }
+ if (axisPtr->obj.name != NULL) {
+ free((void*)(axisPtr->obj.name));
+ }
+ if (axisPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&graphPtr->axes.table, axisPtr->hashPtr);
+ }
+ Blt_Ts_FreeStyle(graphPtr->display, &axisPtr->limitsTextStyle);
+
+ if (axisPtr->tickGC != NULL) {
+ Tk_FreeGC(graphPtr->display, axisPtr->tickGC);
+ }
+ if (axisPtr->activeTickGC != NULL) {
+ Tk_FreeGC(graphPtr->display, axisPtr->activeTickGC);
+ }
+ if (axisPtr->major.gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, axisPtr->major.gc);
+ }
+ if (axisPtr->minor.gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, axisPtr->minor.gc);
+ }
+ FreeTickLabels(axisPtr->tickLabels);
+ Blt_Chain_Destroy(axisPtr->tickLabels);
+ if (axisPtr->segments != NULL) {
+ free(axisPtr->segments);
+ }
+ free(axisPtr);
+ axisPtr = NULL;
+}
+
+static void FreeAxis(char* data)
+{
+ Axis *axisPtr = (Axis *)data;
+ DestroyAxis(axisPtr);
+}
+
+static float titleAngle[4] = /* Rotation for each axis title */
+{
+ 0.0, 90.0, 0.0, 270.0
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisOffsets --
+ *
+ * Determines the sites of the axis, major and minor ticks, and title of
+ * the axis.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+AxisOffsets(
+ Axis *axisPtr,
+ int margin,
+ int offset,
+ AxisInfo *infoPtr)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ Margin *marginPtr;
+ int pad; /* Offset of axis from interior
+ * region. This includes a possible
+ * border and the axis line width. */
+ int axisLine;
+ int t1, t2, labelOffset;
+ int tickLabel, axisPad;
+ int inset, mark;
+ int x, y;
+ float fangle;
+
+ axisPtr->titleAngle = titleAngle[margin];
+ marginPtr = graphPtr->margins + margin;
+
+ tickLabel = axisLine = t1 = t2 = 0;
+ labelOffset = AXIS_PAD_TITLE;
+ if (axisPtr->lineWidth > 0) {
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ t1 = axisPtr->tickLength;
+ t2 = (t1 * 10) / 15;
+ }
+ labelOffset = t1 + AXIS_PAD_TITLE;
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ labelOffset += axisPtr->lineWidth;
+ }
+ }
+ axisPad = 0;
+ if (graphPtr->plotRelief != TK_RELIEF_SOLID) {
+ axisPad = 0;
+ }
+ /* Adjust offset for the interior border width and the line width */
+ pad = 1;
+ if (graphPtr->plotBW > 0) {
+ pad += graphPtr->plotBW + 1;
+ }
+ pad = 0; /* FIXME: test */
+ /*
+ * Pre-calculate the x-coordinate positions of the axis, tick labels, and
+ * the individual major and minor ticks.
+ */
+ inset = pad + axisPtr->lineWidth / 2;
+ switch (margin) {
+ case MARGIN_TOP:
+ axisLine = graphPtr->top;
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ axisLine -= graphPtr->plotBW + axisPad + axisPtr->lineWidth / 2;
+ tickLabel = axisLine - 2;
+ if (axisPtr->lineWidth > 0) {
+ tickLabel -= axisPtr->tickLength;
+ }
+ } else {
+ if (graphPtr->plotRelief == TK_RELIEF_SOLID) {
+ axisLine--;
+ }
+ axisLine -= axisPad + axisPtr->lineWidth / 2;
+ tickLabel = graphPtr->top - graphPtr->plotBW - 2;
+ }
+ mark = graphPtr->top - offset - pad;
+ axisPtr->tickAnchor = TK_ANCHOR_S;
+ axisPtr->left = axisPtr->screenMin - inset - 2;
+ axisPtr->right = axisPtr->screenMin + axisPtr->screenRange + inset - 1;
+ if (graphPtr->stackAxes) {
+ axisPtr->top = mark - marginPtr->axesOffset;
+ } else {
+ axisPtr->top = mark - axisPtr->height;
+ }
+ axisPtr->bottom = mark;
+ if (axisPtr->titleAlternate) {
+ x = graphPtr->right + AXIS_PAD_TITLE;
+ y = mark - (axisPtr->height / 2);
+ axisPtr->titleAnchor = TK_ANCHOR_W;
+ } else {
+ x = (axisPtr->right + axisPtr->left) / 2;
+ if (graphPtr->stackAxes) {
+ y = mark - marginPtr->axesOffset + AXIS_PAD_TITLE;
+ } else {
+ y = mark - axisPtr->height + AXIS_PAD_TITLE;
+ }
+ axisPtr->titleAnchor = TK_ANCHOR_N;
+ }
+ axisPtr->titlePos.x = x;
+ axisPtr->titlePos.y = y;
+ break;
+
+ case MARGIN_BOTTOM:
+ /*
+ * ----------- bottom + plot borderwidth
+ * mark --------------------------------------------
+ * ===================== axisLine (linewidth)
+ * tick
+ * title
+ *
+ * ===================== axisLine (linewidth)
+ * ----------- bottom + plot borderwidth
+ * mark --------------------------------------------
+ * tick
+ * title
+ */
+ axisLine = graphPtr->bottom;
+ if (graphPtr->plotRelief == TK_RELIEF_SOLID) {
+ axisLine++;
+ }
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ axisLine += graphPtr->plotBW + axisPad + axisPtr->lineWidth / 2;
+ tickLabel = axisLine + 2;
+ if (axisPtr->lineWidth > 0) {
+ tickLabel += axisPtr->tickLength;
+ }
+ } else {
+ axisLine -= axisPad + axisPtr->lineWidth / 2;
+ tickLabel = graphPtr->bottom + graphPtr->plotBW + 2;
+ }
+ mark = graphPtr->bottom + offset;
+ fangle = fmod(axisPtr->tickAngle, 90.0);
+ if (fangle == 0.0) {
+ axisPtr->tickAnchor = TK_ANCHOR_N;
+ } else {
+ int quadrant;
+
+ quadrant = (int)(axisPtr->tickAngle / 90.0);
+ if ((quadrant == 0) || (quadrant == 2)) {
+ axisPtr->tickAnchor = TK_ANCHOR_NE;
+ } else {
+ axisPtr->tickAnchor = TK_ANCHOR_NW;
+ }
+ }
+ axisPtr->left = axisPtr->screenMin - inset - 2;
+ axisPtr->right = axisPtr->screenMin + axisPtr->screenRange + inset - 1;
+ axisPtr->top = graphPtr->bottom + labelOffset - t1;
+ if (graphPtr->stackAxes) {
+ axisPtr->bottom = mark + marginPtr->axesOffset - 1;
+ } else {
+ axisPtr->bottom = mark + axisPtr->height - 1;
+ }
+ if (axisPtr->titleAlternate) {
+ x = graphPtr->right + AXIS_PAD_TITLE;
+ y = mark + (axisPtr->height / 2);
+ axisPtr->titleAnchor = TK_ANCHOR_W;
+ } else {
+ x = (axisPtr->right + axisPtr->left) / 2;
+ if (graphPtr->stackAxes) {
+ y = mark + marginPtr->axesOffset - AXIS_PAD_TITLE;
+ } else {
+ y = mark + axisPtr->height - AXIS_PAD_TITLE;
+ }
+ axisPtr->titleAnchor = TK_ANCHOR_S;
+ }
+ axisPtr->titlePos.x = x;
+ axisPtr->titlePos.y = y;
+ break;
+
+ case MARGIN_LEFT:
+ /*
+ * mark
+ * | :
+ * | :
+ * | :
+ * | :
+ * | :
+ * axisLine
+ */
+ /*
+ * Exterior axis
+ * + plotarea right
+ * |A|B|C|D|E|F|G|H
+ * |right
+ * A = plot pad
+ * B = plot border width
+ * C = axis pad
+ * D = axis line
+ * E = tick length
+ * F = tick label
+ * G = graph border width
+ * H = highlight thickness
+ */
+ /*
+ * Interior axis
+ * + plotarea right
+ * |A|B|C|D|E|F|G|H
+ * |right
+ * A = plot pad
+ * B = tick length
+ * C = axis line width
+ * D = axis pad
+ * E = plot border width
+ * F = tick label
+ * G = graph border width
+ * H = highlight thickness
+ */
+ axisLine = graphPtr->left;
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ axisLine -= graphPtr->plotBW + axisPad + axisPtr->lineWidth / 2;
+ tickLabel = axisLine - 2;
+ if (axisPtr->lineWidth > 0) {
+ tickLabel -= axisPtr->tickLength;
+ }
+ } else {
+ if (graphPtr->plotRelief == TK_RELIEF_SOLID) {
+ axisLine--;
+ }
+ axisLine += axisPad + axisPtr->lineWidth / 2;
+ tickLabel = graphPtr->left - graphPtr->plotBW - 2;
+ }
+ mark = graphPtr->left - offset;
+ axisPtr->tickAnchor = TK_ANCHOR_E;
+ if (graphPtr->stackAxes) {
+ axisPtr->left = mark - marginPtr->axesOffset;
+ } else {
+ axisPtr->left = mark - axisPtr->width;
+ }
+ axisPtr->right = mark - 3;
+ axisPtr->top = axisPtr->screenMin - inset - 2;
+ axisPtr->bottom = axisPtr->screenMin + axisPtr->screenRange + inset - 1;
+ if (axisPtr->titleAlternate) {
+ x = mark - (axisPtr->width / 2);
+ y = graphPtr->top - AXIS_PAD_TITLE;
+ axisPtr->titleAnchor = TK_ANCHOR_SW;
+ } else {
+ if (graphPtr->stackAxes) {
+ x = mark - marginPtr->axesOffset;
+ } else {
+ x = mark - axisPtr->width + AXIS_PAD_TITLE;
+ }
+ y = (axisPtr->bottom + axisPtr->top) / 2;
+ axisPtr->titleAnchor = TK_ANCHOR_W;
+ }
+ axisPtr->titlePos.x = x;
+ axisPtr->titlePos.y = y;
+ break;
+
+ case MARGIN_RIGHT:
+ axisLine = graphPtr->right;
+ if (graphPtr->plotRelief == TK_RELIEF_SOLID) {
+ axisLine++; /* Draw axis line within solid plot
+ * border. */
+ }
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ axisLine += graphPtr->plotBW + axisPad + axisPtr->lineWidth / 2;
+ tickLabel = axisLine + 2;
+ if (axisPtr->lineWidth > 0) {
+ tickLabel += axisPtr->tickLength;
+ }
+ } else {
+ axisLine -= axisPad + axisPtr->lineWidth / 2;
+ tickLabel = graphPtr->right + graphPtr->plotBW + 2;
+ }
+ mark = graphPtr->right + offset + pad;
+ axisPtr->tickAnchor = TK_ANCHOR_W;
+ axisPtr->left = mark;
+ if (graphPtr->stackAxes) {
+ axisPtr->right = mark + marginPtr->axesOffset - 1;
+ } else {
+ axisPtr->right = mark + axisPtr->width - 1;
+ }
+ axisPtr->top = axisPtr->screenMin - inset - 2;
+ axisPtr->bottom = axisPtr->screenMin + axisPtr->screenRange + inset -1;
+ if (axisPtr->titleAlternate) {
+ x = mark + (axisPtr->width / 2);
+ y = graphPtr->top - AXIS_PAD_TITLE;
+ axisPtr->titleAnchor = TK_ANCHOR_SE;
+ } else {
+ if (graphPtr->stackAxes) {
+ x = mark + marginPtr->axesOffset - AXIS_PAD_TITLE;
+ } else {
+ x = mark + axisPtr->width - AXIS_PAD_TITLE;
+ }
+ y = (axisPtr->bottom + axisPtr->top) / 2;
+ axisPtr->titleAnchor = TK_ANCHOR_E;
+ }
+ axisPtr->titlePos.x = x;
+ axisPtr->titlePos.y = y;
+ break;
+
+ case MARGIN_NONE:
+ axisLine = 0;
+ break;
+ }
+ if ((margin == MARGIN_LEFT) || (margin == MARGIN_TOP)) {
+ t1 = -t1, t2 = -t2;
+ labelOffset = -labelOffset;
+ }
+ infoPtr->axis = axisLine;
+ infoPtr->t1 = axisLine + t1;
+ infoPtr->t2 = axisLine + t2;
+ if (tickLabel > 0) {
+ infoPtr->label = tickLabel;
+ } else {
+ infoPtr->label = axisLine + labelOffset;
+ }
+ if ((axisPtr->flags & AXIS_EXTERIOR) == 0) {
+ /*infoPtr->label = axisLine + labelOffset - t1; */
+ infoPtr->t1 = axisLine - t1;
+ infoPtr->t2 = axisLine - t2;
+ }
+}
+
+static void
+MakeAxisLine(Axis *axisPtr, int line, Segment2d *sp)
+{
+ double min, max;
+
+ min = axisPtr->axisRange.min;
+ max = axisPtr->axisRange.max;
+ if (axisPtr->logScale) {
+ min = EXP10(min);
+ max = EXP10(max);
+ }
+ if (AxisIsHorizontal(axisPtr)) {
+ sp->p.x = Blt_HMap(axisPtr, min);
+ sp->q.x = Blt_HMap(axisPtr, max);
+ sp->p.y = sp->q.y = line;
+ } else {
+ sp->q.x = sp->p.x = line;
+ sp->p.y = Blt_VMap(axisPtr, min);
+ sp->q.y = Blt_VMap(axisPtr, max);
+ }
+}
+
+
+static void
+MakeTick(Axis *axisPtr, double value, int tick, int line, Segment2d *sp)
+{
+ if (axisPtr->logScale) {
+ value = EXP10(value);
+ }
+ if (AxisIsHorizontal(axisPtr)) {
+ sp->p.x = sp->q.x = Blt_HMap(axisPtr, value);
+ sp->p.y = line;
+ sp->q.y = tick;
+ } else {
+ sp->p.x = line;
+ sp->p.y = sp->q.y = Blt_VMap(axisPtr, value);
+ sp->q.x = tick;
+ }
+}
+
+static void
+MakeSegments(Axis *axisPtr, AxisInfo *infoPtr)
+{
+ int arraySize;
+ int nMajorTicks, nMinorTicks;
+ Segment2d *segments;
+ Segment2d *sp;
+
+ if (axisPtr->segments != NULL) {
+ free(axisPtr->segments);
+ axisPtr->segments = NULL;
+ }
+ nMajorTicks = nMinorTicks = 0;
+ if (axisPtr->t1Ptr != NULL) {
+ nMajorTicks = axisPtr->t1Ptr->nTicks;
+ }
+ if (axisPtr->t2Ptr != NULL) {
+ nMinorTicks = axisPtr->t2Ptr->nTicks;
+ }
+ arraySize = 1 + (nMajorTicks * (nMinorTicks + 1));
+ segments = malloc(arraySize * sizeof(Segment2d));
+ sp = segments;
+ if (axisPtr->lineWidth > 0) {
+ /* Axis baseline */
+ MakeAxisLine(axisPtr, infoPtr->axis, sp);
+ sp++;
+ }
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ Blt_ChainLink link;
+ double labelPos;
+ int i;
+ int isHoriz;
+
+ isHoriz = AxisIsHorizontal(axisPtr);
+ for (i = 0; i < nMajorTicks; i++) {
+ double t1, t2;
+ int j;
+
+ t1 = axisPtr->t1Ptr->values[i];
+ /* Minor ticks */
+ for (j = 0; j < nMinorTicks; j++) {
+ t2 = t1 + (axisPtr->majorSweep.step *
+ axisPtr->t2Ptr->values[j]);
+ if (InRange(t2, &axisPtr->axisRange)) {
+ MakeTick(axisPtr, t2, infoPtr->t2, infoPtr->axis, sp);
+ sp++;
+ }
+ }
+ if (!InRange(t1, &axisPtr->axisRange)) {
+ continue;
+ }
+ /* Major tick */
+ MakeTick(axisPtr, t1, infoPtr->t1, infoPtr->axis, sp);
+ sp++;
+ }
+
+ link = Blt_Chain_FirstLink(axisPtr->tickLabels);
+ labelPos = (double)infoPtr->label;
+
+ for (i = 0; i < nMajorTicks; i++) {
+ double t1;
+ TickLabel *labelPtr;
+ Segment2d seg;
+
+ t1 = axisPtr->t1Ptr->values[i];
+ if (axisPtr->labelOffset) {
+ t1 += axisPtr->majorSweep.step * 0.5;
+ }
+ if (!InRange(t1, &axisPtr->axisRange)) {
+ continue;
+ }
+ labelPtr = Blt_Chain_GetValue(link);
+ link = Blt_Chain_NextLink(link);
+ MakeTick(axisPtr, t1, infoPtr->t1, infoPtr->axis, &seg);
+ /* Save tick label X-Y position. */
+ if (isHoriz) {
+ labelPtr->anchorPos.x = seg.p.x;
+ labelPtr->anchorPos.y = labelPos;
+ } else {
+ labelPtr->anchorPos.x = labelPos;
+ labelPtr->anchorPos.y = seg.p.y;
+ }
+ }
+ }
+ axisPtr->segments = segments;
+ axisPtr->nSegments = sp - segments;
+ assert(axisPtr->nSegments <= arraySize);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapAxis --
+ *
+ * Pre-calculates positions of the axis, ticks, and labels (to be used
+ * later when displaying the axis). Calculates the values for each major
+ * and minor tick and checks to see if they are in range (the outer ticks
+ * may be outside of the range of plotted values).
+ *
+ * Line segments for the minor and major ticks are saved into one
+ * XSegment array so that they can be drawn by a single XDrawSegments
+ * call. The positions of the tick labels are also computed and saved.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Line segments and tick labels are saved and used later to draw the
+ * axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapAxis(Axis *axisPtr, int offset, int margin)
+{
+ AxisInfo info;
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ if (AxisIsHorizontal(axisPtr)) {
+ axisPtr->screenMin = graphPtr->hOffset;
+ axisPtr->width = graphPtr->right - graphPtr->left;
+ axisPtr->screenRange = graphPtr->hRange;
+ } else {
+ axisPtr->screenMin = graphPtr->vOffset;
+ axisPtr->height = graphPtr->bottom - graphPtr->top;
+ axisPtr->screenRange = graphPtr->vRange;
+ }
+ axisPtr->screenScale = 1.0 / axisPtr->screenRange;
+ AxisOffsets(axisPtr, margin, offset, &info);
+ MakeSegments(axisPtr, &info);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapStackedAxis --
+ *
+ * Pre-calculates positions of the axis, ticks, and labels (to be used
+ * later when displaying the axis). Calculates the values for each major
+ * and minor tick and checks to see if they are in range (the outer ticks
+ * may be outside of the range of plotted values).
+ *
+ * Line segments for the minor and major ticks are saved into one XSegment
+ * array so that they can be drawn by a single XDrawSegments call. The
+ * positions of the tick labels are also computed and saved.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Line segments and tick labels are saved and used later to draw the
+ * axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapStackedAxis(Axis *axisPtr, int count, int margin)
+{
+ AxisInfo info;
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ unsigned int slice, w, h;
+
+ if ((graphPtr->margins[axisPtr->margin].axes->nLinks > 1) ||
+ (axisPtr->reqNumMajorTicks <= 0)) {
+ axisPtr->reqNumMajorTicks = 4;
+ }
+ if (AxisIsHorizontal(axisPtr)) {
+ slice = graphPtr->hRange / graphPtr->margins[margin].axes->nLinks;
+ axisPtr->screenMin = graphPtr->hOffset;
+ axisPtr->width = slice;
+ } else {
+ slice = graphPtr->vRange / graphPtr->margins[margin].axes->nLinks;
+ axisPtr->screenMin = graphPtr->vOffset;
+ axisPtr->height = slice;
+ }
+#define AXIS_PAD 2
+ Blt_GetTextExtents(axisPtr->tickFont, 0, "0", 1, &w, &h);
+ axisPtr->screenMin += (slice * count) + AXIS_PAD + h / 2;
+ axisPtr->screenRange = slice - 2 * AXIS_PAD - h;
+ axisPtr->screenScale = 1.0f / axisPtr->screenRange;
+ AxisOffsets(axisPtr, margin, 0, &info);
+ MakeSegments(axisPtr, &info);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AdjustViewport --
+ *
+ * Adjusts the offsets of the viewport according to the scroll mode. This
+ * is to accommodate both "listbox" and "canvas" style scrolling.
+ *
+ * "canvas" The viewport scrolls within the range of world
+ * coordinates. This way the viewport always displays
+ * a full page of the world. If the world is smaller
+ * than the viewport, then (bizarrely) the world and
+ * viewport are inverted so that the world moves up
+ * and down within the viewport.
+ *
+ * "listbox" The viewport can scroll beyond the range of world
+ * coordinates. Every entry can be displayed at the
+ * top of the viewport. This also means that the
+ * scrollbar thumb weirdly shrinks as the last entry
+ * is scrolled upward.
+ *
+ * Results:
+ * The corrected offset is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static double
+AdjustViewport(double offset, double windowSize)
+{
+ /*
+ * Canvas-style scrolling allows the world to be scrolled within the window.
+ */
+ if (windowSize > 1.0) {
+ if (windowSize < (1.0 - offset)) {
+ offset = 1.0 - windowSize;
+ }
+ if (offset > 0.0) {
+ offset = 0.0;
+ }
+ } else {
+ if ((offset + windowSize) > 1.0) {
+ offset = 1.0 - windowSize;
+ }
+ if (offset < 0.0) {
+ offset = 0.0;
+ }
+ }
+ return offset;
+}
+
+static int
+GetAxisScrollInfo(
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv,
+ double *offsetPtr,
+ double windowSize,
+ double scrollUnits,
+ double scale)
+{
+ const char *string;
+ char c;
+ double offset;
+ int length;
+
+ offset = *offsetPtr;
+ string = Tcl_GetStringFromObj(objv[0], &length);
+ c = string[0];
+ scrollUnits *= scale;
+ if ((c == 's') && (strncmp(string, "scroll", length) == 0)) {
+ int count;
+ double fract;
+
+ assert(objc == 3);
+ /* Scroll number unit/page */
+ if (Tcl_GetIntFromObj(interp, objv[1], &count) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ string = Tcl_GetStringFromObj(objv[2], &length);
+ c = string[0];
+ if ((c == 'u') && (strncmp(string, "units", length) == 0)) {
+ fract = count * scrollUnits;
+ } else if ((c == 'p') && (strncmp(string, "pages", length) == 0)) {
+ /* A page is 90% of the view-able window. */
+ fract = (int)(count * windowSize * 0.9 + 0.5);
+ } else if ((c == 'p') && (strncmp(string, "pixels", length) == 0)) {
+ fract = count * scale;
+ } else {
+ Tcl_AppendResult(interp, "unknown \"scroll\" units \"", string,
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ offset += fract;
+ } else if ((c == 'm') && (strncmp(string, "moveto", length) == 0)) {
+ double fract;
+
+ assert(objc == 2);
+ /* moveto fraction */
+ if (Blt_GetDoubleFromObj(interp, objv[1], &fract) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ offset = fract;
+ } else {
+ int count;
+ double fract;
+
+ /* Treat like "scroll units" */
+ if (Tcl_GetIntFromObj(interp, objv[0], &count) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ fract = (double)count * scrollUnits;
+ offset += fract;
+ /* CHECK THIS: return TCL_OK; */
+ }
+ *offsetPtr = AdjustViewport(offset, windowSize);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawAxis --
+ *
+ * Draws the axis, ticks, and labels onto the canvas.
+ *
+ * Initializes and passes text attribute information through TextStyle
+ * structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Axis gets drawn on window.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawAxis(Axis *axisPtr, Drawable drawable)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ if (axisPtr->normalBg != NULL) {
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable,
+ axisPtr->normalBg,
+ axisPtr->left, axisPtr->top,
+ axisPtr->right - axisPtr->left,
+ axisPtr->bottom - axisPtr->top, axisPtr->borderWidth,
+ axisPtr->relief);
+ }
+ if (axisPtr->title != NULL) {
+ TextStyle ts;
+
+ Blt_Ts_InitStyle(ts);
+ Blt_Ts_SetAngle(ts, axisPtr->titleAngle);
+ Blt_Ts_SetFont(ts, axisPtr->titleFont);
+ Blt_Ts_SetPadding(ts, 1, 2, 0, 0);
+ Blt_Ts_SetAnchor(ts, axisPtr->titleAnchor);
+ Blt_Ts_SetJustify(ts, axisPtr->titleJustify);
+ if (axisPtr->flags & ACTIVE) {
+ Blt_Ts_SetForeground(ts, axisPtr->activeFgColor);
+ } else {
+ Blt_Ts_SetForeground(ts, axisPtr->titleColor);
+ }
+ Blt_Ts_SetForeground(ts, axisPtr->titleColor);
+ if ((axisPtr->titleAngle == 90.0) || (axisPtr->titleAngle == 270.0)) {
+ Blt_Ts_SetMaxLength(ts, axisPtr->height);
+ } else {
+ Blt_Ts_SetMaxLength(ts, axisPtr->width);
+ }
+ Blt_Ts_DrawText(graphPtr->tkwin, drawable, axisPtr->title, -1, &ts,
+ (int)axisPtr->titlePos.x, (int)axisPtr->titlePos.y);
+ }
+ if (axisPtr->scrollCmdObjPtr != NULL) {
+ double viewWidth, viewMin, viewMax;
+ double worldWidth, worldMin, worldMax;
+ double fract;
+ int isHoriz;
+
+ worldMin = axisPtr->valueRange.min;
+ worldMax = axisPtr->valueRange.max;
+ if (isnormal(axisPtr->scrollMin)) {
+ worldMin = axisPtr->scrollMin;
+ }
+ if (isnormal(axisPtr->scrollMax)) {
+ worldMax = axisPtr->scrollMax;
+ }
+ viewMin = axisPtr->min;
+ viewMax = axisPtr->max;
+ if (viewMin < worldMin) {
+ viewMin = worldMin;
+ }
+ if (viewMax > worldMax) {
+ viewMax = worldMax;
+ }
+ if (axisPtr->logScale) {
+ worldMin = log10(worldMin);
+ worldMax = log10(worldMax);
+ viewMin = log10(viewMin);
+ viewMax = log10(viewMax);
+ }
+ worldWidth = worldMax - worldMin;
+ viewWidth = viewMax - viewMin;
+ isHoriz = AxisIsHorizontal(axisPtr);
+
+ if (isHoriz != axisPtr->descending) {
+ fract = (viewMin - worldMin) / worldWidth;
+ } else {
+ fract = (worldMax - viewMax) / worldWidth;
+ }
+ fract = AdjustViewport(fract, viewWidth / worldWidth);
+
+ if (isHoriz != axisPtr->descending) {
+ viewMin = (fract * worldWidth);
+ axisPtr->min = viewMin + worldMin;
+ axisPtr->max = axisPtr->min + viewWidth;
+ viewMax = viewMin + viewWidth;
+ if (axisPtr->logScale) {
+ axisPtr->min = EXP10(axisPtr->min);
+ axisPtr->max = EXP10(axisPtr->max);
+ }
+ Blt_UpdateScrollbar(graphPtr->interp, axisPtr->scrollCmdObjPtr,
+ viewMin, viewMax, worldWidth);
+ } else {
+ viewMax = (fract * worldWidth);
+ axisPtr->max = worldMax - viewMax;
+ axisPtr->min = axisPtr->max - viewWidth;
+ viewMin = viewMax + viewWidth;
+ if (axisPtr->logScale) {
+ axisPtr->min = EXP10(axisPtr->min);
+ axisPtr->max = EXP10(axisPtr->max);
+ }
+ Blt_UpdateScrollbar(graphPtr->interp, axisPtr->scrollCmdObjPtr,
+ viewMax, viewMin, worldWidth);
+ }
+ }
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ Blt_ChainLink link;
+ TextStyle ts;
+
+ Blt_Ts_InitStyle(ts);
+ Blt_Ts_SetAngle(ts, axisPtr->tickAngle);
+ Blt_Ts_SetFont(ts, axisPtr->tickFont);
+ Blt_Ts_SetPadding(ts, 2, 0, 0, 0);
+ Blt_Ts_SetAnchor(ts, axisPtr->tickAnchor);
+ if (axisPtr->flags & ACTIVE) {
+ Blt_Ts_SetForeground(ts, axisPtr->activeFgColor);
+ } else {
+ Blt_Ts_SetForeground(ts, axisPtr->tickColor);
+ }
+ for (link = Blt_Chain_FirstLink(axisPtr->tickLabels); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ TickLabel *labelPtr;
+
+ labelPtr = Blt_Chain_GetValue(link);
+ /* Draw major tick labels */
+ Blt_DrawText(graphPtr->tkwin, drawable, labelPtr->string, &ts,
+ (int)labelPtr->anchorPos.x, (int)labelPtr->anchorPos.y);
+ }
+ }
+ if ((axisPtr->nSegments > 0) && (axisPtr->lineWidth > 0)) {
+ GC gc;
+
+ if (axisPtr->flags & ACTIVE) {
+ gc = axisPtr->activeTickGC;
+ } else {
+ gc = axisPtr->tickGC;
+ }
+ /* Draw the tick marks and axis line. */
+ Blt_Draw2DSegments(graphPtr->display, drawable, gc, axisPtr->segments,
+ axisPtr->nSegments);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisToPostScript --
+ *
+ * Generates PostScript output to draw the axis, ticks, and labels.
+ *
+ * Initializes and passes text attribute information through TextStyle
+ * structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * PostScript output is left in graphPtr->interp->result;
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+AxisToPostScript(Blt_Ps ps, Axis *axisPtr)
+{
+ Blt_Ps_Format(ps, "%% Axis \"%s\"\n", axisPtr->obj.name);
+ if (axisPtr->normalBg != NULL) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(axisPtr->normalBg);
+ Blt_Ps_Fill3DRectangle(ps, border,
+ (double)axisPtr->left, (double)axisPtr->top,
+ axisPtr->right - axisPtr->left, axisPtr->bottom - axisPtr->top,
+ axisPtr->borderWidth, axisPtr->relief);
+ }
+ if (axisPtr->title != NULL) {
+ TextStyle ts;
+
+ Blt_Ts_InitStyle(ts);
+ Blt_Ts_SetAngle(ts, axisPtr->titleAngle);
+ Blt_Ts_SetFont(ts, axisPtr->titleFont);
+ Blt_Ts_SetPadding(ts, 1, 2, 0, 0);
+ Blt_Ts_SetAnchor(ts, axisPtr->titleAnchor);
+ Blt_Ts_SetJustify(ts, axisPtr->titleJustify);
+ Blt_Ts_SetForeground(ts, axisPtr->titleColor);
+ Blt_Ps_DrawText(ps, axisPtr->title, &ts, axisPtr->titlePos.x,
+ axisPtr->titlePos.y);
+ }
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ Blt_ChainLink link;
+ TextStyle ts;
+
+ Blt_Ts_InitStyle(ts);
+ Blt_Ts_SetAngle(ts, axisPtr->tickAngle);
+ Blt_Ts_SetFont(ts, axisPtr->tickFont);
+ Blt_Ts_SetPadding(ts, 2, 0, 0, 0);
+ Blt_Ts_SetAnchor(ts, axisPtr->tickAnchor);
+ Blt_Ts_SetForeground(ts, axisPtr->tickColor);
+
+ for (link = Blt_Chain_FirstLink(axisPtr->tickLabels); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ TickLabel *labelPtr;
+
+ labelPtr = Blt_Chain_GetValue(link);
+ Blt_Ps_DrawText(ps, labelPtr->string, &ts, labelPtr->anchorPos.x,
+ labelPtr->anchorPos.y);
+ }
+ }
+ if ((axisPtr->nSegments > 0) && (axisPtr->lineWidth > 0)) {
+ Blt_Ps_XSetLineAttributes(ps, axisPtr->tickColor, axisPtr->lineWidth,
+ (Blt_Dashes *)NULL, CapButt, JoinMiter);
+ Blt_Ps_Draw2DSegments(ps, axisPtr->segments, axisPtr->nSegments);
+ }
+}
+
+static void
+MakeGridLine(Axis *axisPtr, double value, Segment2d *sp)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ if (axisPtr->logScale) {
+ value = EXP10(value);
+ }
+ /* Grid lines run orthogonally to the axis */
+ if (AxisIsHorizontal(axisPtr)) {
+ sp->p.y = graphPtr->top;
+ sp->q.y = graphPtr->bottom;
+ sp->p.x = sp->q.x = Blt_HMap(axisPtr, value);
+ } else {
+ sp->p.x = graphPtr->left;
+ sp->q.x = graphPtr->right;
+ sp->p.y = sp->q.y = Blt_VMap(axisPtr, value);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapGridlines --
+ *
+ * Assembles the grid lines associated with an axis. Generates tick
+ * positions if necessary (this happens when the axis is not a logical axis
+ * too).
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapGridlines(Axis *axisPtr)
+{
+ Segment2d *s1, *s2;
+ Ticks *t1Ptr, *t2Ptr;
+ int needed;
+ int i;
+
+ if (axisPtr == NULL) {
+ return;
+ }
+ t1Ptr = axisPtr->t1Ptr;
+ if (t1Ptr == NULL) {
+ t1Ptr = GenerateTicks(&axisPtr->majorSweep);
+ }
+ t2Ptr = axisPtr->t2Ptr;
+ if (t2Ptr == NULL) {
+ t2Ptr = GenerateTicks(&axisPtr->minorSweep);
+ }
+ needed = t1Ptr->nTicks;
+ if (axisPtr->flags & AXIS_GRIDMINOR) {
+ needed += (t1Ptr->nTicks * t2Ptr->nTicks);
+ }
+ if (needed == 0) {
+ return;
+ }
+ needed = t1Ptr->nTicks;
+ if (needed != axisPtr->major.nAllocated) {
+ if (axisPtr->major.segments != NULL) {
+ free(axisPtr->major.segments);
+ axisPtr->major.segments = NULL;
+ }
+ axisPtr->major.segments = malloc(sizeof(Segment2d) * needed);
+ axisPtr->major.nAllocated = needed;
+ }
+ needed = (t1Ptr->nTicks * t2Ptr->nTicks);
+ if (needed != axisPtr->minor.nAllocated) {
+ if (axisPtr->minor.segments != NULL) {
+ free(axisPtr->minor.segments);
+ axisPtr->minor.segments = NULL;
+ }
+ axisPtr->minor.segments = malloc(sizeof(Segment2d) * needed);
+ axisPtr->minor.nAllocated = needed;
+ }
+ s1 = axisPtr->major.segments, s2 = axisPtr->minor.segments;
+ for (i = 0; i < t1Ptr->nTicks; i++) {
+ double value;
+
+ value = t1Ptr->values[i];
+ if (axisPtr->flags & AXIS_GRIDMINOR) {
+ int j;
+
+ for (j = 0; j < t2Ptr->nTicks; j++) {
+ double subValue;
+
+ subValue = value + (axisPtr->majorSweep.step *
+ t2Ptr->values[j]);
+ if (InRange(subValue, &axisPtr->axisRange)) {
+ MakeGridLine(axisPtr, subValue, s2);
+ s2++;
+ }
+ }
+ }
+ if (InRange(value, &axisPtr->axisRange)) {
+ MakeGridLine(axisPtr, value, s1);
+ s1++;
+ }
+ }
+ if (t1Ptr != axisPtr->t1Ptr) {
+ free(t1Ptr); /* Free generated ticks. */
+ }
+ if (t2Ptr != axisPtr->t2Ptr) {
+ free(t2Ptr); /* Free generated ticks. */
+ }
+ axisPtr->major.nUsed = s1 - axisPtr->major.segments;
+ axisPtr->minor.nUsed = s2 - axisPtr->minor.segments;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetAxisGeometry --
+ *
+ * Results:
+ * None.
+ *
+ * Exterior axis:
+ * l r
+ * |a|b|c|d|e|f|g|h|i| j |i|h|g|f|e|d|c|d|a|
+ *
+ * Interior axis:
+ * l r
+ * |a|b|c|d|h|g|f|e| j |e|f|g|h|d|c|b|a|
+ * i.. ..i
+ * a = highlight thickness
+ * b = graph borderwidth
+ * c = axis title
+ * d = tick label
+ * e = tick
+ * f = axis line
+ * g = 1 pixel pad
+ * h = plot borderwidth
+ * i = plot pad
+ * j = plot area
+ *---------------------------------------------------------------------------
+ */
+static void
+GetAxisGeometry(Graph *graphPtr, Axis *axisPtr)
+{
+ unsigned int y;
+
+ FreeTickLabels(axisPtr->tickLabels);
+ y = 0;
+
+ if ((axisPtr->flags & AXIS_EXTERIOR) &&
+ (graphPtr->plotRelief != TK_RELIEF_SOLID)) {
+ /* Leave room for axis baseline and padding */
+ y += axisPtr->lineWidth + 2;
+ }
+
+ axisPtr->maxTickHeight = axisPtr->maxTickWidth = 0;
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ unsigned int pad;
+ unsigned int i, nLabels, nTicks;
+
+ SweepTicks(axisPtr);
+
+ nTicks = 0;
+ if (axisPtr->t1Ptr != NULL) {
+ nTicks = axisPtr->t1Ptr->nTicks;
+ }
+ assert(nTicks <= MAXTICKS);
+
+ nLabels = 0;
+ for (i = 0; i < nTicks; i++) {
+ TickLabel *labelPtr;
+ double x, x2;
+ unsigned int lw, lh; /* Label width and height. */
+
+ x2 = x = axisPtr->t1Ptr->values[i];
+ if (axisPtr->labelOffset) {
+ x2 += axisPtr->majorSweep.step * 0.5;
+ }
+ if (!InRange(x2, &axisPtr->axisRange)) {
+ continue;
+ }
+ labelPtr = MakeLabel(axisPtr, x);
+ Blt_Chain_Append(axisPtr->tickLabels, labelPtr);
+ nLabels++;
+ /*
+ * Get the dimensions of each tick label. Remember tick labels
+ * can be multi-lined and/or rotated.
+ */
+ Blt_GetTextExtents(axisPtr->tickFont, 0, labelPtr->string, -1,
+ &lw, &lh);
+ labelPtr->width = lw;
+ labelPtr->height = lh;
+
+ if (axisPtr->tickAngle != 0.0f) {
+ double rlw, rlh; /* Rotated label width and height. */
+ Blt_GetBoundingBox(lw, lh, axisPtr->tickAngle, &rlw, &rlh,NULL);
+ lw = ROUND(rlw), lh = ROUND(rlh);
+ }
+ if (axisPtr->maxTickWidth < lw) {
+ axisPtr->maxTickWidth = lw;
+ }
+ if (axisPtr->maxTickHeight < lh) {
+ axisPtr->maxTickHeight = lh;
+ }
+ }
+ assert(nLabels <= nTicks);
+
+ pad = 0;
+ if (axisPtr->flags & AXIS_EXTERIOR) {
+ /* Because the axis cap style is "CapProjecting", we need to
+ * account for an extra 1.5 linewidth at the end of each line. */
+ pad = ((axisPtr->lineWidth * 12) / 8);
+ }
+ if (AxisIsHorizontal(axisPtr)) {
+ y += axisPtr->maxTickHeight + pad;
+ } else {
+ y += axisPtr->maxTickWidth + pad;
+ if (axisPtr->maxTickWidth > 0) {
+ y += 5; /* Pad either size of label. */
+ }
+ }
+ y += 2 * AXIS_PAD_TITLE;
+ if ((axisPtr->lineWidth > 0) && (axisPtr->flags & AXIS_EXTERIOR)) {
+ /* Distance from axis line to tick label. */
+ y += axisPtr->tickLength;
+ }
+ }
+
+ if (axisPtr->title != NULL) {
+ if (axisPtr->titleAlternate) {
+ if (y < axisPtr->titleHeight) {
+ y = axisPtr->titleHeight;
+ }
+ } else {
+ y += axisPtr->titleHeight + AXIS_PAD_TITLE;
+ }
+ }
+
+ /* Correct for orientation of the axis. */
+ if (AxisIsHorizontal(axisPtr)) {
+ axisPtr->height = y;
+ } else {
+ axisPtr->width = y;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetMarginGeometry --
+ *
+ * Examines all the axes in the given margin and determines the area
+ * required to display them.
+ *
+ * Note: For multiple axes, the titles are displayed in another
+ * margin. So we must keep track of the widest title.
+ *
+ * Results:
+ * Returns the width or height of the margin, depending if it runs
+ * horizontally along the graph or vertically.
+ *
+ * Side Effects:
+ * The area width and height set in the margin. Note again that this may
+ * be corrected later (mulitple axes) to adjust for the longest title in
+ * another margin.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+GetMarginGeometry(Graph *graphPtr, Margin *marginPtr)
+{
+ Blt_ChainLink link;
+ unsigned int l, w, h; /* Length, width, and height. */
+ int isHoriz;
+ unsigned int nVisible;
+
+ isHoriz = HORIZMARGIN(marginPtr);
+
+ /* Count the visible axes. */
+ nVisible = 0;
+ l = w = h = 0;
+ marginPtr->maxTickWidth = marginPtr->maxTickHeight = 0;
+ if (graphPtr->stackAxes) {
+ for (link = Blt_Chain_FirstLink(marginPtr->axes); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (HIDE|AXIS_USE)) == AXIS_USE) {
+ nVisible++;
+ if (graphPtr->flags & GET_AXIS_GEOMETRY) {
+ GetAxisGeometry(graphPtr, axisPtr);
+ }
+ if (isHoriz) {
+ if (h < axisPtr->height) {
+ h = axisPtr->height;
+ }
+ } else {
+ if (w < axisPtr->width) {
+ w = axisPtr->width;
+ }
+ }
+ if (axisPtr->maxTickWidth > marginPtr->maxTickWidth) {
+ marginPtr->maxTickWidth = axisPtr->maxTickWidth;
+ }
+ if (axisPtr->maxTickHeight > marginPtr->maxTickHeight) {
+ marginPtr->maxTickHeight = axisPtr->maxTickHeight;
+ }
+ }
+ }
+ } else {
+ for (link = Blt_Chain_FirstLink(marginPtr->axes); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (HIDE|AXIS_USE)) == AXIS_USE) {
+ nVisible++;
+ if (graphPtr->flags & GET_AXIS_GEOMETRY) {
+ GetAxisGeometry(graphPtr, axisPtr);
+ }
+ if ((axisPtr->titleAlternate) && (l < axisPtr->titleWidth)) {
+ l = axisPtr->titleWidth;
+ }
+ if (isHoriz) {
+ h += axisPtr->height;
+ } else {
+ w += axisPtr->width;
+ }
+ if (axisPtr->maxTickWidth > marginPtr->maxTickWidth) {
+ marginPtr->maxTickWidth = axisPtr->maxTickWidth;
+ }
+ if (axisPtr->maxTickHeight > marginPtr->maxTickHeight) {
+ marginPtr->maxTickHeight = axisPtr->maxTickHeight;
+ }
+ }
+ }
+ }
+ /* Enforce a minimum size for margins. */
+ if (w < 3) {
+ w = 3;
+ }
+ if (h < 3) {
+ h = 3;
+ }
+ marginPtr->nAxes = nVisible;
+ marginPtr->axesTitleLength = l;
+ marginPtr->width = w;
+ marginPtr->height = h;
+ marginPtr->axesOffset = (isHoriz) ? h : w;
+ return marginPtr->axesOffset;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_LayoutGraph --
+ *
+ * Calculate the layout of the graph. Based upon the data, axis limits,
+ * X and Y titles, and title height, determine the cavity left which is
+ * the plotting surface. The first step get the data and axis limits for
+ * calculating the space needed for the top, bottom, left, and right
+ * margins.
+ *
+ * 1) The LEFT margin is the area from the left border to the Y axis
+ * (not including ticks). It composes the border width, the width an
+ * optional Y axis label and its padding, and the tick numeric labels.
+ * The Y axis label is rotated 90 degrees so that the width is the
+ * font height.
+ *
+ * 2) The RIGHT margin is the area from the end of the graph
+ * to the right window border. It composes the border width,
+ * some padding, the font height (this may be dubious. It
+ * appears to provide a more even border), the max of the
+ * legend width and 1/2 max X tick number. This last part is
+ * so that the last tick label is not clipped.
+ *
+ * Window Width
+ * ___________________________________________________________
+ * | | | |
+ * | | TOP height of title | |
+ * | | | |
+ * | | x2 title | |
+ * | | | |
+ * | | height of x2-axis | |
+ * |__________|_______________________________|_______________| W
+ * | | -plotpady | | i
+ * |__________|_______________________________|_______________| n
+ * | | top right | | d
+ * | | | | o
+ * | LEFT | | RIGHT | w
+ * | | | |
+ * | y | Free area = 104% | y2 | H
+ * | | Plotting surface = 100% | | e
+ * | t | Tick length = 2 + 2% | t | i
+ * | i | | i | g
+ * | t | | t legend| h
+ * | l | | l width| t
+ * | e | | e |
+ * | height| |height |
+ * | of | | of |
+ * | y-axis| |y2-axis |
+ * | | | |
+ * | |origin 0,0 | |
+ * |__________|_left_________________bottom___|_______________|
+ * | |-plotpady | |
+ * |__________|_______________________________|_______________|
+ * | | (xoffset, yoffset) | |
+ * | | | |
+ * | | height of x-axis | |
+ * | | | |
+ * | | BOTTOM x title | |
+ * |__________|_______________________________|_______________|
+ *
+ * 3) The TOP margin is the area from the top window border to the top
+ * of the graph. It composes the border width, twice the height of
+ * the title font (if one is given) and some padding between the
+ * title.
+ *
+ * 4) The BOTTOM margin is area from the bottom window border to the
+ * X axis (not including ticks). It composes the border width, the height
+ * an optional X axis label and its padding, the height of the font
+ * of the tick labels.
+ *
+ * The plotting area is between the margins which includes the X and Y axes
+ * including the ticks but not the tick numeric labels. The length of the
+ * ticks and its padding is 5% of the entire plotting area. Hence the entire
+ * plotting area is scaled as 105% of the width and height of the area.
+ *
+ * The axis labels, ticks labels, title, and legend may or may not be
+ * displayed which must be taken into account.
+ *
+ * if reqWidth > 0 : set outer size
+ * if reqPlotWidth > 0 : set plot size
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_LayoutGraph(Graph *graphPtr)
+{
+ unsigned int titleY;
+ unsigned int left, right, top, bottom;
+ unsigned int plotWidth, plotHeight;
+ unsigned int inset, inset2;
+ int width, height;
+ int pad;
+
+ width = graphPtr->width;
+ height = graphPtr->height;
+
+ /*
+ * Step 1: Compute the amount of space needed to display the axes
+ * associated with each margin. They can be overridden by
+ * -leftmargin, -rightmargin, -bottommargin, and -topmargin
+ * graph options, respectively.
+ */
+ left = GetMarginGeometry(graphPtr, &graphPtr->leftMargin);
+ right = GetMarginGeometry(graphPtr, &graphPtr->rightMargin);
+ top = GetMarginGeometry(graphPtr, &graphPtr->topMargin);
+ bottom = GetMarginGeometry(graphPtr, &graphPtr->bottomMargin);
+
+ pad = graphPtr->bottomMargin.maxTickWidth;
+ if (pad < graphPtr->topMargin.maxTickWidth) {
+ pad = graphPtr->topMargin.maxTickWidth;
+ }
+ pad = pad / 2 + 3;
+ if (right < pad) {
+ right = pad;
+ }
+ if (left < pad) {
+ left = pad;
+ }
+ pad = graphPtr->leftMargin.maxTickHeight;
+ if (pad < graphPtr->rightMargin.maxTickHeight) {
+ pad = graphPtr->rightMargin.maxTickHeight;
+ }
+ pad = pad / 2;
+ if (top < pad) {
+ top = pad;
+ }
+ if (bottom < pad) {
+ bottom = pad;
+ }
+
+ if (graphPtr->leftMargin.reqSize > 0) {
+ left = graphPtr->leftMargin.reqSize;
+ }
+ if (graphPtr->rightMargin.reqSize > 0) {
+ right = graphPtr->rightMargin.reqSize;
+ }
+ if (graphPtr->topMargin.reqSize > 0) {
+ top = graphPtr->topMargin.reqSize;
+ }
+ if (graphPtr->bottomMargin.reqSize > 0) {
+ bottom = graphPtr->bottomMargin.reqSize;
+ }
+
+ /*
+ * Step 2: Add the graph title height to the top margin.
+ */
+ if (graphPtr->title != NULL) {
+ top += graphPtr->titleHeight + 6;
+ }
+ inset = (graphPtr->inset + graphPtr->plotBW);
+ inset2 = 2 * inset;
+
+ /*
+ * Step 3: Estimate the size of the plot area from the remaining
+ * space. This may be overridden by the -plotwidth and
+ * -plotheight graph options. We use this to compute the
+ * size of the legend.
+ */
+ if (width == 0) {
+ width = 400;
+ }
+ if (height == 0) {
+ height = 400;
+ }
+ plotWidth = (graphPtr->reqPlotWidth > 0) ? graphPtr->reqPlotWidth :
+ width - (inset2 + left + right); /* Plot width. */
+ plotHeight = (graphPtr->reqPlotHeight > 0) ? graphPtr->reqPlotHeight :
+ height - (inset2 + top + bottom); /* Plot height. */
+ Blt_MapLegend(graphPtr, plotWidth, plotHeight);
+
+ /*
+ * Step 2: Add the legend to the appropiate margin.
+ */
+ if (!Blt_Legend_IsHidden(graphPtr)) {
+ switch (Blt_Legend_Site(graphPtr)) {
+ case LEGEND_RIGHT:
+ right += Blt_Legend_Width(graphPtr) + 2;
+ break;
+ case LEGEND_LEFT:
+ left += Blt_Legend_Width(graphPtr) + 2;
+ break;
+ case LEGEND_TOP:
+ top += Blt_Legend_Height(graphPtr) + 2;
+ break;
+ case LEGEND_BOTTOM:
+ bottom += Blt_Legend_Height(graphPtr) + 2;
+ break;
+ case LEGEND_XY:
+ case LEGEND_PLOT:
+ case LEGEND_WINDOW:
+ /* Do nothing. */
+ break;
+ }
+ }
+
+ /*
+ * Recompute the plotarea or graph size, now accounting for the legend.
+ */
+ if (graphPtr->reqPlotWidth == 0) {
+ plotWidth = width - (inset2 + left + right);
+ if (plotWidth < 1) {
+ plotWidth = 1;
+ }
+ }
+ if (graphPtr->reqPlotHeight == 0) {
+ plotHeight = height - (inset2 + top + bottom);
+ if (plotHeight < 1) {
+ plotHeight = 1;
+ }
+ }
+
+ /*
+ * Step 5: If necessary, correct for the requested plot area aspect
+ * ratio.
+ */
+ if ((graphPtr->reqPlotWidth == 0) && (graphPtr->reqPlotHeight == 0) &&
+ (graphPtr->aspect > 0.0f)) {
+ float ratio;
+
+ /*
+ * Shrink one dimension of the plotarea to fit the requested
+ * width/height aspect ratio.
+ */
+ ratio = (float)plotWidth / (float)plotHeight;
+ if (ratio > graphPtr->aspect) {
+ int scaledWidth;
+
+ /* Shrink the width. */
+ scaledWidth = (int)(plotHeight * graphPtr->aspect);
+ if (scaledWidth < 1) {
+ scaledWidth = 1;
+ }
+ /* Add the difference to the right margin. */
+ /* CHECK THIS: w = scaledWidth; */
+ right += (plotWidth - scaledWidth);
+ } else {
+ int scaledHeight;
+
+ /* Shrink the height. */
+ scaledHeight = (int)(plotWidth / graphPtr->aspect);
+ if (scaledHeight < 1) {
+ scaledHeight = 1;
+ }
+ /* Add the difference to the top margin. */
+ /* CHECK THIS: h = scaledHeight; */
+ top += (plotHeight - scaledHeight);
+ }
+ }
+
+ /*
+ * Step 6: If there's multiple axes in a margin, the axis titles will be
+ * displayed in the adjoining margins. Make sure there's room
+ * for the longest axis titles.
+ */
+
+ if (top < graphPtr->leftMargin.axesTitleLength) {
+ top = graphPtr->leftMargin.axesTitleLength;
+ }
+ if (right < graphPtr->bottomMargin.axesTitleLength) {
+ right = graphPtr->bottomMargin.axesTitleLength;
+ }
+ if (top < graphPtr->rightMargin.axesTitleLength) {
+ top = graphPtr->rightMargin.axesTitleLength;
+ }
+ if (right < graphPtr->topMargin.axesTitleLength) {
+ right = graphPtr->topMargin.axesTitleLength;
+ }
+
+ /*
+ * Step 7: Override calculated values with requested margin sizes.
+ */
+ if (graphPtr->leftMargin.reqSize > 0) {
+ left = graphPtr->leftMargin.reqSize;
+ }
+ if (graphPtr->rightMargin.reqSize > 0) {
+ right = graphPtr->rightMargin.reqSize;
+ }
+ if (graphPtr->topMargin.reqSize > 0) {
+ top = graphPtr->topMargin.reqSize;
+ }
+ if (graphPtr->bottomMargin.reqSize > 0) {
+ bottom = graphPtr->bottomMargin.reqSize;
+ }
+ if (graphPtr->reqPlotWidth > 0) {
+ int w;
+
+ /*
+ * Width of plotarea is constained. If there's extra space, add it to
+ * th left and/or right margins. If there's too little, grow the
+ * graph width to accomodate it.
+ */
+ w = plotWidth + inset2 + left + right;
+ if (width > w) { /* Extra space in window. */
+ int extra;
+
+ extra = (width - w) / 2;
+ if (graphPtr->leftMargin.reqSize == 0) {
+ left += extra;
+ if (graphPtr->rightMargin.reqSize == 0) {
+ right += extra;
+ } else {
+ left += extra;
+ }
+ } else if (graphPtr->rightMargin.reqSize == 0) {
+ right += extra + extra;
+ }
+ } else if (width < w) {
+ width = w;
+ }
+ }
+ if (graphPtr->reqPlotHeight > 0) { /* Constrain the plotarea height. */
+ int h;
+
+ /*
+ * Height of plotarea is constained. If there's extra space,
+ * add it to th top and/or bottom margins. If there's too little,
+ * grow the graph height to accomodate it.
+ */
+ h = plotHeight + inset2 + top + bottom;
+ if (height > h) { /* Extra space in window. */
+ int extra;
+
+ extra = (height - h) / 2;
+ if (graphPtr->topMargin.reqSize == 0) {
+ top += extra;
+ if (graphPtr->bottomMargin.reqSize == 0) {
+ bottom += extra;
+ } else {
+ top += extra;
+ }
+ } else if (graphPtr->bottomMargin.reqSize == 0) {
+ bottom += extra + extra;
+ }
+ } else if (height < h) {
+ height = h;
+ }
+ }
+ graphPtr->width = width;
+ graphPtr->height = height;
+ graphPtr->left = left + inset;
+ graphPtr->top = top + inset;
+ graphPtr->right = width - right - inset;
+ graphPtr->bottom = height - bottom - inset;
+
+ graphPtr->leftMargin.width = left + graphPtr->inset;
+ graphPtr->rightMargin.width = right + graphPtr->inset;
+ graphPtr->topMargin.height = top + graphPtr->inset;
+ graphPtr->bottomMargin.height = bottom + graphPtr->inset;
+
+ graphPtr->vOffset = graphPtr->top + graphPtr->padTop;
+ graphPtr->vRange = plotHeight - PADDING(graphPtr->yPad);
+ graphPtr->hOffset = graphPtr->left + graphPtr->padLeft;
+ graphPtr->hRange = plotWidth - PADDING(graphPtr->xPad);
+
+ if (graphPtr->vRange < 1) {
+ graphPtr->vRange = 1;
+ }
+ if (graphPtr->hRange < 1) {
+ graphPtr->hRange = 1;
+ }
+ graphPtr->hScale = 1.0f / (float)graphPtr->hRange;
+ graphPtr->vScale = 1.0f / (float)graphPtr->vRange;
+
+ /*
+ * Calculate the placement of the graph title so it is centered within the
+ * space provided for it in the top margin
+ */
+ titleY = graphPtr->titleHeight;
+ graphPtr->titleY = 3 + graphPtr->inset;
+ graphPtr->titleX = (graphPtr->right + graphPtr->left) / 2;
+
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureAxis --
+ *
+ * Configures axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ * Axis layout is deferred until the height and width of the window are
+ * known.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureAxis(Axis *axisPtr)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ float angle;
+
+ /* Check the requested axis limits. Can't allow -min to be greater than
+ * -max. Do this regardless of -checklimits option. We want to always
+ * detect when the user has zoomed in beyond the precision of the data.*/
+ if (((isnormal(axisPtr->reqMin)) && (isnormal(axisPtr->reqMax))) &&
+ (axisPtr->reqMin >= axisPtr->reqMax)) {
+ char msg[200];
+ sprintf_s(msg, 200,
+ "impossible axis limits (-min %g >= -max %g) for \"%s\"",
+ axisPtr->reqMin, axisPtr->reqMax, axisPtr->obj.name);
+ Tcl_AppendResult(graphPtr->interp, msg, (char *)NULL);
+ return TCL_ERROR;
+ }
+ axisPtr->scrollMin = axisPtr->reqScrollMin;
+ axisPtr->scrollMax = axisPtr->reqScrollMax;
+ if (axisPtr->logScale) {
+ if (axisPtr->flags & AXIS_CHECK_LIMITS) {
+ /* Check that the logscale limits are positive. */
+ if ((isnormal(axisPtr->reqMin)) && (axisPtr->reqMin <= 0.0)) {
+ Tcl_AppendResult(graphPtr->interp,"bad logscale -min limit \"",
+ Blt_Dtoa(graphPtr->interp, axisPtr->reqMin),
+ "\" for axis \"", axisPtr->obj.name, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((isnormal(axisPtr->scrollMin)) && (axisPtr->scrollMin <= 0.0)) {
+ axisPtr->scrollMin = NAN;
+ }
+ if ((isnormal(axisPtr->scrollMax)) && (axisPtr->scrollMax <= 0.0)) {
+ axisPtr->scrollMax = NAN;
+ }
+ }
+ angle = fmod(axisPtr->tickAngle, 360.0);
+ if (angle < 0.0f) {
+ angle += 360.0f;
+ }
+ if (axisPtr->normalBg != NULL) {
+ Blt_SetBackgroundChangedProc(axisPtr->normalBg, Blt_UpdateGraph,
+ graphPtr);
+ }
+ if (axisPtr->activeBg != NULL) {
+ Blt_SetBackgroundChangedProc(axisPtr->activeBg, Blt_UpdateGraph,
+ graphPtr);
+ }
+ axisPtr->tickAngle = angle;
+ ResetTextStyles(axisPtr);
+
+ axisPtr->titleWidth = axisPtr->titleHeight = 0;
+ if (axisPtr->title != NULL) {
+ unsigned int w, h;
+
+ Blt_GetTextExtents(axisPtr->titleFont, 0, axisPtr->title, -1, &w, &h);
+ axisPtr->titleWidth = (unsigned short int)w;
+ axisPtr->titleHeight = (unsigned short int)h;
+ }
+
+ /*
+ * Don't bother to check what configuration options have changed. Almost
+ * every option changes the size of the plotting area (except for -color
+ * and -titlecolor), requiring the graph and its contents to be completely
+ * redrawn.
+ *
+ * Recompute the scale and offset of the axis in case -min, -max options
+ * have changed.
+ */
+ graphPtr->flags |= REDRAW_WORLD;
+ graphPtr->flags |= MAP_WORLD | RESET_AXES | CACHE_DIRTY;
+ axisPtr->flags |= DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NewAxis --
+ *
+ * Create and initialize a structure containing information to display
+ * a graph axis.
+ *
+ * Results:
+ * The return value is a pointer to an Axis structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Axis *
+NewAxis(Graph *graphPtr, const char *name, int margin)
+{
+ Axis *axisPtr;
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ if (name[0] == '-') {
+ Tcl_AppendResult(graphPtr->interp, "name of axis \"", name,
+ "\" can't start with a '-'", (char *)NULL);
+ return NULL;
+ }
+ hPtr = Blt_CreateHashEntry(&graphPtr->axes.table, name, &isNew);
+ if (!isNew) {
+ axisPtr = Blt_GetHashValue(hPtr);
+ if ((axisPtr->flags & DELETE_PENDING) == 0) {
+ Tcl_AppendResult(graphPtr->interp, "axis \"", name,
+ "\" already exists in \"", Tk_PathName(graphPtr->tkwin), "\"",
+ (char *)NULL);
+ return NULL;
+ }
+ axisPtr->flags &= ~DELETE_PENDING;
+ } else {
+ axisPtr = calloc(1, sizeof(Axis));
+ if (axisPtr == NULL) {
+ Tcl_AppendResult(graphPtr->interp,
+ "can't allocate memory for axis \"", name, "\"", (char *)NULL);
+ return NULL;
+ }
+ axisPtr->obj.name = Blt_Strdup(name);
+ axisPtr->hashPtr = hPtr;
+ Blt_GraphSetObjectClass(&axisPtr->obj, CID_NONE);
+ axisPtr->obj.graphPtr = graphPtr;
+ axisPtr->looseMin = axisPtr->looseMax = AXIS_TIGHT;
+ axisPtr->reqNumMinorTicks = 2;
+ axisPtr->reqNumMajorTicks = 4 /*10*/;
+ axisPtr->margin = MARGIN_NONE;
+ axisPtr->tickLength = 8;
+ axisPtr->scrollUnits = 10;
+ axisPtr->reqMin = axisPtr->reqMax = NAN;
+ axisPtr->reqScrollMin = axisPtr->reqScrollMax = NAN;
+ axisPtr->flags = (AXIS_SHOWTICKS|AXIS_GRIDMINOR|AXIS_AUTO_MAJOR|
+ AXIS_AUTO_MINOR | AXIS_EXTERIOR);
+ if (graphPtr->classId == CID_ELEM_BAR) {
+ axisPtr->flags |= AXIS_GRID;
+ }
+ if ((graphPtr->classId == CID_ELEM_BAR) &&
+ ((margin == MARGIN_TOP) || (margin == MARGIN_BOTTOM))) {
+ axisPtr->reqStep = 1.0;
+ axisPtr->reqNumMinorTicks = 0;
+ }
+ if ((margin == MARGIN_RIGHT) || (margin == MARGIN_TOP)) {
+ axisPtr->flags |= HIDE;
+ }
+ Blt_Ts_InitStyle(axisPtr->limitsTextStyle);
+ axisPtr->tickLabels = Blt_Chain_Create();
+ axisPtr->lineWidth = 1;
+ Blt_SetHashValue(hPtr, axisPtr);
+ }
+ return axisPtr;
+}
+
+static int
+GetAxisFromObj(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ Axis **axisPtrPtr)
+{
+ Blt_HashEntry *hPtr;
+ const char *name;
+
+ *axisPtrPtr = NULL;
+ name = Tcl_GetString(objPtr);
+ hPtr = Blt_FindHashEntry(&graphPtr->axes.table, name);
+ if (hPtr != NULL) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ if ((axisPtr->flags & DELETE_PENDING) == 0) {
+ *axisPtrPtr = axisPtr;
+ return TCL_OK;
+ }
+ }
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find axis \"", name, "\" in \"",
+ Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+}
+
+static int
+GetAxisByClass(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ ClassId classId, Axis **axisPtrPtr)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objPtr, &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (classId != CID_NONE) {
+ if ((axisPtr->refCount == 0) || (axisPtr->obj.classId == CID_NONE)) {
+ /* Set the axis type on the first use of it. */
+ Blt_GraphSetObjectClass(&axisPtr->obj, classId);
+ } else if (axisPtr->obj.classId != classId) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "axis \"", Tcl_GetString(objPtr),
+ "\" is already in use on an opposite ",
+ axisPtr->obj.className, "-axis",
+ (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ axisPtr->refCount++;
+ }
+ *axisPtrPtr = axisPtr;
+ return TCL_OK;
+}
+
+void
+Blt_DestroyAxes(Graph *graphPtr)
+{
+ {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ axisPtr->hashPtr = NULL;
+ DestroyAxis(axisPtr);
+ }
+ }
+ Blt_DeleteHashTable(&graphPtr->axes.table);
+ {
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ Blt_Chain_Destroy(graphPtr->axisChain[i]);
+ }
+ }
+ Blt_DeleteHashTable(&graphPtr->axes.tagTable);
+ Blt_Chain_Destroy(graphPtr->axes.displayList);
+}
+
+void
+Blt_ConfigureAxes(Graph *graphPtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ ConfigureAxis(axisPtr);
+ }
+}
+
+int
+Blt_DefaultAxes(Graph *graphPtr)
+{
+ int i;
+ int flags;
+
+ flags = Blt_GraphType(graphPtr);
+ for (i = 0; i < 4; i++) {
+ Blt_Chain chain;
+ Axis *axisPtr;
+
+ chain = Blt_Chain_Create();
+ graphPtr->axisChain[i] = chain;
+
+ /* Create a default axis for each chain. */
+ axisPtr = NewAxis(graphPtr, axisNames[i].name, i);
+ if (axisPtr == NULL) {
+ return TCL_ERROR;
+ }
+ axisPtr->refCount = 1; /* Default axes are assumed in use. */
+ axisPtr->margin = i;
+ axisPtr->flags |= AXIS_USE;
+ Blt_GraphSetObjectClass(&axisPtr->obj, axisNames[i].classId);
+ /*
+ * Blt_ConfigureComponentFromObj creates a temporary child window
+ * by the name of the axis. It's used so that the Tk routines
+ * that access the X resource database can describe a single
+ * component and not the entire graph.
+ */
+ if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
+ axisPtr->obj.name, "Axis", configSpecs, 0, (Tcl_Obj **)NULL,
+ (char *)axisPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ConfigureAxis(axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ axisPtr->link = Blt_Chain_Append(chain, axisPtr);
+ axisPtr->chain = chain;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ActivateOp --
+ *
+ * Activates the axis, drawing the axis with its -activeforeground,
+ * -activebackgound, -activerelief attributes.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new axis attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ActivateOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ const char *string;
+
+ string = Tcl_GetString(objv[2]);
+ if (string[0] == 'a') {
+ axisPtr->flags |= ACTIVE;
+ } else {
+ axisPtr->flags &= ~ACTIVE;
+ }
+ if ((axisPtr->flags & (AXIS_USE|HIDE)) == AXIS_USE) {
+ graphPtr->flags |= DRAW_MARGINS | CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ return TCL_OK;
+}
+
+/*-------------------------------------------------------------------------------
+ *
+ * BindOp --
+ *
+ * .g axis bind axisName sequence command
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+BindOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->bindTable,
+ Blt_MakeAxisTag(graphPtr, axisPtr->obj.name), objc, objv);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ * Queries axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * Return value is a standard TCL result. If querying configuration
+ * values, interp->result will contain the results.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+CgetOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+
+ return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)axisPtr, objv[0], Blt_GraphType(graphPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Queries or resets axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * Return value is a standard TCL result. If querying configuration
+ * values, interp->result will contain the results.
+ *
+ * Side Effects:
+ * Axis resources are possibly allocated (GC, font). Axis layout is
+ * deferred until the height and width of the window are known.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ int flags;
+
+ flags = BLT_CONFIG_OBJV_ONLY | Blt_GraphType(graphPtr);
+ if (objc == 0) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)axisPtr, (Tcl_Obj *)NULL, flags);
+ } else if (objc == 1) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)axisPtr, objv[0], flags);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc, objv, (char *)axisPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ConfigureAxis(axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (axisPtr->flags & AXIS_USE) {
+ if (!Blt_ConfigModified(configSpecs, "-*color", "-background", "-bg",
+ (char *)NULL)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LimitsOp --
+ *
+ * This procedure returns a string representing the axis limits
+ * of the graph. The format of the string is { left top right bottom}.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is
+ * a list of the graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+LimitsOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ Tcl_Obj *listObjPtr;
+ double min, max;
+
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ if (axisPtr->logScale) {
+ min = EXP10(axisPtr->axisRange.min);
+ max = EXP10(axisPtr->axisRange.max);
+ } else {
+ min = axisPtr->axisRange.min;
+ max = axisPtr->axisRange.max;
+ }
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(min));
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(max));
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InvTransformOp --
+ *
+ * Maps the given window coordinate into an axis-value.
+ *
+ * Results:
+ * Returns a standard TCL result. interp->result contains
+ * the axis value. If an error occurred, TCL_ERROR is returned
+ * and interp->result will contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+InvTransformOp(Tcl_Interp *interp, Axis *axisPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ double y; /* Real graph coordinate */
+ int sy; /* Integer window coordinate*/
+
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ if (Tcl_GetIntFromObj(interp, objv[0], &sy) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Is the axis vertical or horizontal?
+ *
+ * Check the site where the axis was positioned. If the axis is
+ * virtual, all we have to go on is how it was mapped to an
+ * element (using either -mapx or -mapy options).
+ */
+ if (AxisIsHorizontal(axisPtr)) {
+ y = Blt_InvHMap(axisPtr, (double)sy);
+ } else {
+ y = Blt_InvVMap(axisPtr, (double)sy);
+ }
+ Tcl_SetDoubleObj(Tcl_GetObjResult(interp), y);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MarginOp --
+ *
+ * This procedure returns a string representing the margin the axis
+ * resides. The format of the string is { left top right bottom}.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is
+ * a list of the graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+MarginOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ const char *marginName;
+
+ marginName = "";
+ if (axisPtr->flags & AXIS_USE) {
+ marginName = axisNames[axisPtr->margin].name;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), marginName, -1);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TransformOp --
+ *
+ * Maps the given axis-value to a window coordinate.
+ *
+ * Results:
+ * Returns a standard TCL result. interp->result contains
+ * the window coordinate. If an error occurred, TCL_ERROR
+ * is returned and interp->result will contain an error
+ * message.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TransformOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = axisPtr->obj.graphPtr;
+ double x;
+
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ if (Blt_ExprDoubleFromObj(interp, objv[0], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AxisIsHorizontal(axisPtr)) {
+ x = Blt_HMap(axisPtr, x);
+ } else {
+ x = Blt_VMap(axisPtr, x);
+ }
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), (int)x);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TypeOp --
+ *
+ * This procedure returns a string representing the margin the axis
+ * resides. The format of the string is "x", "y", or "".
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is the type of
+ * axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TypeOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ const char *typeName;
+
+ typeName = "";
+ if (axisPtr->flags & AXIS_USE) {
+ if (axisNames[axisPtr->margin].classId == CID_AXIS_X) {
+ typeName = "x";
+ } else if (axisNames[axisPtr->margin].classId == CID_AXIS_Y) {
+ typeName = "y";
+ }
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), typeName, -1);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UseOp --
+ *
+ * Sets the default axis for a margin.
+ *
+ * Results:
+ * A standard TCL result. If the named axis doesn't exist
+ * an error message is put in interp->result.
+ *
+ * .g xaxis use "abc def gah"
+ * .g xaxis use [lappend abc [.g axis use]]
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+UseOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr = (Graph *)axisPtr;
+ Blt_Chain chain;
+ Blt_ChainLink link;
+ Tcl_Obj **axisObjv;
+ ClassId classId;
+ int axisObjc;
+ int i;
+
+ chain = graphPtr->margins[lastMargin].axes;
+ if (objc == 0) {
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (link = Blt_Chain_FirstLink(chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(axisPtr->obj.name, -1));
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ if ((lastMargin == MARGIN_BOTTOM) || (lastMargin == MARGIN_TOP)) {
+ classId = (graphPtr->inverted) ? CID_AXIS_Y : CID_AXIS_X;
+ } else {
+ classId = (graphPtr->inverted) ? CID_AXIS_X : CID_AXIS_Y;
+ }
+ if (Tcl_ListObjGetElements(interp, objv[0], &axisObjc, &axisObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (link = Blt_Chain_FirstLink(chain); link!= NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ axisPtr->link = NULL;
+ axisPtr->flags &= ~AXIS_USE;
+ /* Clear the axis type if it's not currently used.*/
+ if (axisPtr->refCount == 0) {
+ Blt_GraphSetObjectClass(&axisPtr->obj, CID_NONE);
+ }
+ }
+ Blt_Chain_Reset(chain);
+ for (i = 0; i < axisObjc; i++) {
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, axisObjv[i], &axisPtr) != TCL_OK){
+ return TCL_ERROR;
+ }
+ if (axisPtr->obj.classId == CID_NONE) {
+ Blt_GraphSetObjectClass(&axisPtr->obj, classId);
+ } else if (axisPtr->obj.classId != classId) {
+ Tcl_AppendResult(interp, "wrong type axis \"",
+ axisPtr->obj.name, "\": can't use ",
+ axisPtr->obj.className, " type axis.", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (axisPtr->link != NULL) {
+ /* Move the axis from the old margin's "use" list to the new. */
+ Blt_Chain_UnlinkLink(axisPtr->chain, axisPtr->link);
+ Blt_Chain_AppendLink(chain, axisPtr->link);
+ } else {
+ axisPtr->link = Blt_Chain_Append(chain, axisPtr);
+ }
+ axisPtr->chain = chain;
+ axisPtr->flags |= AXIS_USE;
+ }
+ graphPtr->flags |= (GET_AXIS_GEOMETRY | LAYOUT_NEEDED | RESET_AXES);
+ /* When any axis changes, we need to layout the entire graph. */
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+static int
+ViewOp(Tcl_Interp *interp, Axis *axisPtr, int objc, Tcl_Obj *const *objv)
+{
+ Graph *graphPtr;
+ double axisOffset, axisScale;
+ double fract;
+ double viewMin, viewMax, worldMin, worldMax;
+ double viewWidth, worldWidth;
+
+ graphPtr = axisPtr->obj.graphPtr;
+ worldMin = axisPtr->valueRange.min;
+ worldMax = axisPtr->valueRange.max;
+ /* Override data dimensions with user-selected limits. */
+ if (isnormal(axisPtr->scrollMin)) {
+ worldMin = axisPtr->scrollMin;
+ }
+ if (isnormal(axisPtr->scrollMax)) {
+ worldMax = axisPtr->scrollMax;
+ }
+ viewMin = axisPtr->min;
+ viewMax = axisPtr->max;
+ /* Bound the view within scroll region. */
+ if (viewMin < worldMin) {
+ viewMin = worldMin;
+ }
+ if (viewMax > worldMax) {
+ viewMax = worldMax;
+ }
+ if (axisPtr->logScale) {
+ worldMin = log10(worldMin);
+ worldMax = log10(worldMax);
+ viewMin = log10(viewMin);
+ viewMax = log10(viewMax);
+ }
+ worldWidth = worldMax - worldMin;
+ viewWidth = viewMax - viewMin;
+
+ /* Unlike horizontal axes, vertical axis values run opposite of the
+ * scrollbar first/last values. So instead of pushing the axis minimum
+ * around, we move the maximum instead. */
+ if (AxisIsHorizontal(axisPtr) != axisPtr->descending) {
+ axisOffset = viewMin - worldMin;
+ axisScale = graphPtr->hScale;
+ } else {
+ axisOffset = worldMax - viewMax;
+ axisScale = graphPtr->vScale;
+ }
+ if (objc == 4) {
+ Tcl_Obj *listObjPtr;
+ double first, last;
+
+ first = Clamp(axisOffset / worldWidth);
+ last = Clamp((axisOffset + viewWidth) / worldWidth);
+ listObjPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(first));
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(last));
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ fract = axisOffset / worldWidth;
+ if (GetAxisScrollInfo(interp, objc, objv, &fract,
+ viewWidth / worldWidth, axisPtr->scrollUnits, axisScale) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AxisIsHorizontal(axisPtr) != axisPtr->descending) {
+ axisPtr->reqMin = (fract * worldWidth) + worldMin;
+ axisPtr->reqMax = axisPtr->reqMin + viewWidth;
+ } else {
+ axisPtr->reqMax = worldMax - (fract * worldWidth);
+ axisPtr->reqMin = axisPtr->reqMax - viewWidth;
+ }
+ if (axisPtr->logScale) {
+ axisPtr->reqMin = EXP10(axisPtr->reqMin);
+ axisPtr->reqMax = EXP10(axisPtr->reqMax);
+ }
+ graphPtr->flags |= (GET_AXIS_GEOMETRY | LAYOUT_NEEDED | RESET_AXES);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisCreateOp --
+ *
+ * Creates a new axis.
+ *
+ * Results:
+ * Returns a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+AxisCreateOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+ int flags;
+
+ axisPtr = NewAxis(graphPtr, Tcl_GetString(objv[3]), MARGIN_NONE);
+ if (axisPtr == NULL) {
+ return TCL_ERROR;
+ }
+ flags = Blt_GraphType(graphPtr);
+ if ((Blt_ConfigureComponentFromObj(interp, graphPtr->tkwin,
+ axisPtr->obj.name, "Axis", configSpecs, objc - 4, objv + 4,
+ (char *)axisPtr, flags) != TCL_OK) ||
+ (ConfigureAxis(axisPtr) != TCL_OK)) {
+ DestroyAxis(axisPtr);
+ return TCL_ERROR;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), axisPtr->obj.name, -1);
+ return TCL_OK;
+}
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisActivateOp --
+ *
+ * Activates the axis, drawing the axis with its -activeforeground,
+ * -activebackgound, -activerelief attributes.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new axis attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisActivateOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return ActivateOp(interp, axisPtr, objc, objv);
+}
+
+
+/*-------------------------------------------------------------------------------
+ *
+ * AxisBindOp --
+ *
+ * .g axis bind axisName sequence command
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+AxisBindOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.tagTable, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ const char *tagName;
+ Tcl_Obj *objPtr;
+
+ tagName = Blt_GetHashKey(&graphPtr->axes.tagTable, hPtr);
+ objPtr = Tcl_NewStringObj(tagName, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->bindTable,
+ Blt_MakeAxisTag(graphPtr, Tcl_GetString(objv[3])), objc - 4, objv + 4);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisCgetOp --
+ *
+ * Queries axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * Return value is a standard TCL result. If querying configuration
+ * values, interp->result will contain the results.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+AxisCgetOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return CgetOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisConfigureOp --
+ *
+ * Queries or resets axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * Return value is a standard TCL result. If querying configuration
+ * values, interp->result will contain the results.
+ *
+ * Side Effects:
+ * Axis resources are possibly allocated (GC, font). Axis layout is
+ * deferred until the height and width of the window are known.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisConfigureOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *const *options;
+ int i;
+ int nNames, nOpts;
+
+ /* Figure out where the option value pairs begin */
+ objc -= 3;
+ objv += 3;
+ for (i = 0; i < objc; i++) {
+ Axis *axisPtr;
+ const char *string;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ break;
+ }
+ if (GetAxisFromObj(interp, graphPtr, objv[i], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ nNames = i; /* Number of pen names specified */
+ nOpts = objc - i; /* Number of options specified */
+ options = objv + i; /* Start of options in objv */
+
+ for (i = 0; i < nNames; i++) {
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[i], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ConfigureOp(interp, axisPtr, nOpts, options) != TCL_OK) {
+ break;
+ }
+ }
+ if (i < nNames) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisDeleteOp --
+ *
+ * Deletes one or more axes. The actual removal may be deferred until the
+ * axis is no longer used by any element. The axis can't be referenced by
+ * its name any longer and it may be recreated.
+ *
+ * Results:
+ * Returns a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+AxisDeleteOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[i], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ axisPtr->flags |= DELETE_PENDING;
+ if (axisPtr->refCount == 0) {
+ Tcl_EventuallyFree(axisPtr, FreeAxis);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisFocusOp --
+ *
+ * Activates the axis, drawing the axis with its -activeforeground,
+ * -activebackgound, -activerelief attributes.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new axis attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisFocusOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ if (objc > 3) {
+ Axis *axisPtr;
+ const char *string;
+
+ axisPtr = NULL;
+ string = Tcl_GetString(objv[3]);
+ if ((string[0] != '\0') &&
+ (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ graphPtr->focusPtr = NULL;
+ if ((axisPtr != NULL) &&
+ ((axisPtr->flags & (AXIS_USE|HIDE)) == AXIS_USE)) {
+ graphPtr->focusPtr = axisPtr;
+ }
+ Blt_SetFocusItem(graphPtr->bindTable, graphPtr->focusPtr, NULL);
+ }
+ /* Return the name of the axis that has focus. */
+ if (graphPtr->focusPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ graphPtr->focusPtr->obj.name, -1);
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisGetOp --
+ *
+ * Returns the name of the picked axis (using the axis bind operation).
+ * Right now, the only name accepted is "current".
+ *
+ * Results:
+ * A standard TCL result. The interpreter result will contain the name of
+ * the axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+AxisGetOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetCurrentItem(graphPtr->bindTable);
+ /* Report only on axes. */
+ if ((axisPtr != NULL) &&
+ ((axisPtr->obj.classId == CID_AXIS_X) ||
+ (axisPtr->obj.classId == CID_AXIS_Y) ||
+ (axisPtr->obj.classId == CID_NONE))) {
+ char c;
+ char *string;
+
+ string = Tcl_GetString(objv[3]);
+ c = string[0];
+ if ((c == 'c') && (strcmp(string, "current") == 0)) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), axisPtr->obj.name,-1);
+ } else if ((c == 'd') && (strcmp(string, "detail") == 0)) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), axisPtr->detail, -1);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisInvTransformOp --
+ *
+ * Maps the given window coordinate into an axis-value.
+ *
+ * Results:
+ * Returns a standard TCL result. interp->result contains
+ * the axis value. If an error occurred, TCL_ERROR is returned
+ * and interp->result will contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisInvTransformOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return InvTransformOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisLimitsOp --
+ *
+ * This procedure returns a string representing the axis limits of the
+ * graph. The format of the string is { left top right bottom}.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is
+ * a list of the graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisLimitsOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return LimitsOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisMarginOp --
+ *
+ * This procedure returns a string representing the axis limits of the
+ * graph. The format of the string is { left top right bottom}.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is
+ * a list of the graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisMarginOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return MarginOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisNamesOp --
+ *
+ * Return a list of the names of all the axes.
+ *
+ * Results:
+ * Returns a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*ARGSUSED*/
+static int
+AxisNamesOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ if (axisPtr->flags & DELETE_PENDING) {
+ continue;
+ }
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(axisPtr->obj.name, -1));
+ }
+ } else {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+ int i;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ for (i = 3; i < objc; i++) {
+ const char *pattern;
+
+ pattern = Tcl_GetString(objv[i]);
+ if (Tcl_StringMatch(axisPtr->obj.name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(axisPtr->obj.name, -1));
+ break;
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisTransformOp --
+ *
+ * Maps the given axis-value to a window coordinate.
+ *
+ * Results:
+ * Returns the window coordinate via interp->result. If an error occurred,
+ * TCL_ERROR is returned and interp->result will contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisTransformOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TransformOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisMarginOp --
+ *
+ * This procedure returns a string representing the axis limits of the
+ * graph. The format of the string is { left top right bottom}.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is
+ * a list of the graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AxisTypeOp(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TypeOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+
+static int
+AxisViewOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Axis *axisPtr;
+
+ if (GetAxisFromObj(interp, graphPtr, objv[3], &axisPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return ViewOp(interp, axisPtr, objc - 4, objv + 4);
+}
+
+static Blt_OpSpec virtAxisOps[] = {
+ {"activate", 1, AxisActivateOp, 4, 4, "axisName"},
+ {"bind", 1, AxisBindOp, 3, 6, "axisName sequence command"},
+ {"cget", 2, AxisCgetOp, 5, 5, "axisName option"},
+ {"configure", 2, AxisConfigureOp, 4, 0, "axisName ?axisName?... "
+ "?option value?..."},
+ {"create", 2, AxisCreateOp, 4, 0, "axisName ?option value?..."},
+ {"deactivate", 3, AxisActivateOp, 4, 4, "axisName"},
+ {"delete", 3, AxisDeleteOp, 3, 0, "?axisName?..."},
+ {"focus", 1, AxisFocusOp, 3, 4, "?axisName?"},
+ {"get", 1, AxisGetOp, 4, 4, "name"},
+ {"invtransform", 1, AxisInvTransformOp, 5, 5, "axisName value"},
+ {"limits", 1, AxisLimitsOp, 4, 4, "axisName"},
+ {"margin", 1, AxisMarginOp, 4, 4, "axisName"},
+ {"names", 1, AxisNamesOp, 3, 0, "?pattern?..."},
+ {"transform", 2, AxisTransformOp, 5, 5, "axisName value"},
+ {"type", 2, AxisTypeOp, 4, 4, "axisName"},
+ {"view", 1, AxisViewOp, 4, 7, "axisName ?moveto fract? "
+ "?scroll number what?"},
+};
+static int nVirtAxisOps = sizeof(virtAxisOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_VirtualAxisOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphVirtualAxisProc *proc;
+ int result;
+
+ proc = Blt_GetOpFromObj(interp, nVirtAxisOps, virtAxisOps, BLT_OP_ARG2,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ result = (*proc) (interp, graphPtr, objc, objv);
+ return result;
+}
+
+static Blt_OpSpec axisOps[] = {
+ {"activate", 1, ActivateOp, 3, 3, "",},
+ {"bind", 1, BindOp, 2, 5, "sequence command",},
+ {"cget", 2, CgetOp, 4, 4, "option",},
+ {"configure", 2, ConfigureOp, 3, 0, "?option value?...",},
+ {"deactivate", 1, ActivateOp, 3, 3, "",},
+ {"invtransform", 1, InvTransformOp, 4, 4, "value",},
+ {"limits", 1, LimitsOp, 3, 3, "",},
+ {"transform", 1, TransformOp, 4, 4, "value",},
+ {"use", 1, UseOp, 3, 4, "?axisName?",},
+ {"view", 1, ViewOp, 3, 6, "?moveto fract? ",},
+};
+
+static int nAxisOps = sizeof(axisOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_AxisOp(Tcl_Interp *interp, Graph *graphPtr, int margin, int objc,
+ Tcl_Obj *const *objv)
+{
+ int result;
+ GraphAxisProc *proc;
+
+ proc = Blt_GetOpFromObj(interp, nAxisOps, axisOps, BLT_OP_ARG2,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ if (proc == UseOp) {
+ lastMargin = margin; /* Set global variable to the margin
+ * in the argument list. Needed only
+ * for UseOp. */
+ result = (*proc)(interp, (Axis *)graphPtr, objc - 3, objv + 3);
+ } else {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetFirstAxis(graphPtr->margins[margin].axes);
+ if (axisPtr == NULL) {
+ return TCL_OK;
+ }
+ result = (*proc)(interp, axisPtr, objc - 3, objv + 3);
+ }
+ return result;
+}
+
+void
+Blt_MapAxes(Graph *graphPtr)
+{
+ int margin;
+
+ for (margin = 0; margin < 4; margin++) {
+ Blt_Chain chain;
+ Blt_ChainLink link;
+ int count, offset;
+
+ chain = graphPtr->margins[margin].axes;
+ count = offset = 0;
+ for (link = Blt_Chain_FirstLink(chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (AXIS_USE|DELETE_PENDING)) != AXIS_USE) {
+ continue;
+ }
+ if (graphPtr->stackAxes) {
+ if (axisPtr->reqNumMajorTicks <= 0) {
+ axisPtr->reqNumMajorTicks = 4;
+ }
+ MapStackedAxis(axisPtr, count, margin);
+ } else {
+ if (axisPtr->reqNumMajorTicks <= 0) {
+ axisPtr->reqNumMajorTicks = 4;
+ }
+ MapAxis(axisPtr, offset, margin);
+ }
+ if (axisPtr->flags & AXIS_GRID) {
+ MapGridlines(axisPtr);
+ }
+ offset += (AxisIsHorizontal(axisPtr))
+ ? axisPtr->height : axisPtr->width;
+ count++;
+ }
+ }
+}
+
+void
+Blt_DrawAxes(Graph *graphPtr, Drawable drawable)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->margins[i].axes);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (DELETE_PENDING|HIDE|AXIS_USE)) == AXIS_USE) {
+ DrawAxis(axisPtr, drawable);
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawGrids --
+ *
+ * Draws the grid lines associated with each axis.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawGrids(Graph *graphPtr, Drawable drawable)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->margins[i].axes); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if (axisPtr->flags & (DELETE_PENDING|HIDE)) {
+ continue;
+ }
+ if ((axisPtr->flags & AXIS_USE) && (axisPtr->flags & AXIS_GRID)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable,
+ axisPtr->major.gc, axisPtr->major.segments,
+ axisPtr->major.nUsed);
+ if (axisPtr->flags & AXIS_GRIDMINOR) {
+ Blt_Draw2DSegments(graphPtr->display, drawable,
+ axisPtr->minor.gc, axisPtr->minor.segments,
+ axisPtr->minor.nUsed);
+ }
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GridsToPostScript --
+ *
+ * Draws the grid lines associated with each axis.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_GridsToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->margins[i].axes); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (DELETE_PENDING|HIDE|AXIS_USE|AXIS_GRID)) !=
+ (AXIS_GRID|AXIS_USE)) {
+ continue;
+ }
+ Blt_Ps_Format(ps, "%% Axis %s: grid line attributes\n",
+ axisPtr->obj.name);
+ Blt_Ps_XSetLineAttributes(ps, axisPtr->major.color,
+ axisPtr->major.lineWidth, &axisPtr->major.dashes, CapButt,
+ JoinMiter);
+ Blt_Ps_Format(ps, "%% Axis %s: major grid line segments\n",
+ axisPtr->obj.name);
+ Blt_Ps_Draw2DSegments(ps, axisPtr->major.segments,
+ axisPtr->major.nUsed);
+ if (axisPtr->flags & AXIS_GRIDMINOR) {
+ Blt_Ps_XSetLineAttributes(ps, axisPtr->minor.color,
+ axisPtr->minor.lineWidth, &axisPtr->minor.dashes, CapButt,
+ JoinMiter);
+ Blt_Ps_Format(ps, "%% Axis %s: minor grid line segments\n",
+ axisPtr->obj.name);
+ Blt_Ps_Draw2DSegments(ps, axisPtr->minor.segments,
+ axisPtr->minor.nUsed);
+ }
+ }
+ }
+}
+
+void
+Blt_AxesToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ Margin *mp, *mend;
+
+ for (mp = graphPtr->margins, mend = mp + 4; mp < mend; mp++) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(mp->axes); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_Chain_GetValue(link);
+ if ((axisPtr->flags & (DELETE_PENDING|HIDE|AXIS_USE)) == AXIS_USE) {
+ AxisToPostScript(ps, axisPtr);
+ }
+ }
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawAxisLimits --
+ *
+ * Draws the min/max values of the axis in the plotting area. The text
+ * strings are formatted according to the "sprintf" format descriptors in
+ * the limitsFormats array.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Draws the numeric values of the axis limits into the outer regions of
+ * the plotting area.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawAxisLimits(Graph *graphPtr, Drawable drawable)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+ char minString[200], maxString[200];
+ int vMin, hMin, vMax, hMax;
+
+#define SPACING 8
+ vMin = vMax = graphPtr->left + graphPtr->padLeft + 2;
+ hMin = hMax = graphPtr->bottom - graphPtr->padBottom - 2; /* Offsets */
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+ Dim2D textDim;
+ const char *minFmt, *maxFmt;
+ char *minPtr, *maxPtr;
+ int isHoriz;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ if (axisPtr->flags & DELETE_PENDING) {
+ continue;
+ }
+ if (axisPtr->nFormats == 0) {
+ continue;
+ }
+ isHoriz = AxisIsHorizontal(axisPtr);
+ minPtr = maxPtr = NULL;
+ minFmt = maxFmt = axisPtr->limitsFormats[0];
+ if (axisPtr->nFormats > 1) {
+ maxFmt = axisPtr->limitsFormats[1];
+ }
+ if (minFmt[0] != '\0') {
+ minPtr = minString;
+ sprintf_s(minString, 200, minFmt, axisPtr->axisRange.min);
+ }
+ if (maxFmt[0] != '\0') {
+ maxPtr = maxString;
+ sprintf_s(maxString, 200, maxFmt, axisPtr->axisRange.max);
+ }
+ if (axisPtr->descending) {
+ char *tmp;
+
+ tmp = minPtr, minPtr = maxPtr, maxPtr = tmp;
+ }
+ if (maxPtr != NULL) {
+ if (isHoriz) {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 90.0);
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_SE);
+ Blt_DrawText2(graphPtr->tkwin, drawable, maxPtr,
+ &axisPtr->limitsTextStyle, graphPtr->right, hMax, &textDim);
+ hMax -= (textDim.height + SPACING);
+ } else {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 0.0);
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_NW);
+ Blt_DrawText2(graphPtr->tkwin, drawable, maxPtr,
+ &axisPtr->limitsTextStyle, vMax, graphPtr->top, &textDim);
+ vMax += (textDim.width + SPACING);
+ }
+ }
+ if (minPtr != NULL) {
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_SW);
+ if (isHoriz) {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 90.0);
+ Blt_DrawText2(graphPtr->tkwin, drawable, minPtr,
+ &axisPtr->limitsTextStyle, graphPtr->left, hMin, &textDim);
+ hMin -= (textDim.height + SPACING);
+ } else {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 0.0);
+ Blt_DrawText2(graphPtr->tkwin, drawable, minPtr,
+ &axisPtr->limitsTextStyle, vMin, graphPtr->bottom, &textDim);
+ vMin += (textDim.width + SPACING);
+ }
+ }
+ } /* Loop on axes */
+}
+
+void
+Blt_AxisLimitsToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+ double vMin, hMin, vMax, hMax;
+ char string[200];
+
+#define SPACING 8
+ vMin = vMax = graphPtr->left + graphPtr->padLeft + 2;
+ hMin = hMax = graphPtr->bottom - graphPtr->padBottom - 2; /* Offsets */
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+ const char *minFmt, *maxFmt;
+ unsigned int textWidth, textHeight;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ if (axisPtr->flags & DELETE_PENDING) {
+ continue;
+ }
+ if (axisPtr->nFormats == 0) {
+ continue;
+ }
+ minFmt = maxFmt = axisPtr->limitsFormats[0];
+ if (axisPtr->nFormats > 1) {
+ maxFmt = axisPtr->limitsFormats[1];
+ }
+ if (*maxFmt != '\0') {
+ sprintf_s(string, 200, maxFmt, axisPtr->axisRange.max);
+ Blt_GetTextExtents(axisPtr->tickFont, 0, string, -1, &textWidth,
+ &textHeight);
+ if ((textWidth > 0) && (textHeight > 0)) {
+ if (axisPtr->obj.classId == CID_AXIS_X) {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 90.0);
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_SE);
+ Blt_Ps_DrawText(ps, string, &axisPtr->limitsTextStyle,
+ (double)graphPtr->right, hMax);
+ hMax -= (textWidth + SPACING);
+ } else {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 0.0);
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_NW);
+ Blt_Ps_DrawText(ps, string, &axisPtr->limitsTextStyle,
+ vMax, (double)graphPtr->top);
+ vMax += (textWidth + SPACING);
+ }
+ }
+ }
+ if (*minFmt != '\0') {
+ sprintf_s(string, 200, minFmt, axisPtr->axisRange.min);
+ Blt_GetTextExtents(axisPtr->tickFont, 0, string, -1, &textWidth,
+ &textHeight);
+ if ((textWidth > 0) && (textHeight > 0)) {
+ Blt_Ts_SetAnchor(axisPtr->limitsTextStyle, TK_ANCHOR_SW);
+ if (axisPtr->obj.classId == CID_AXIS_X) {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 90.0);
+ Blt_Ps_DrawText(ps, string, &axisPtr->limitsTextStyle,
+ (double)graphPtr->left, hMin);
+ hMin -= (textWidth + SPACING);
+ } else {
+ Blt_Ts_SetAngle(axisPtr->limitsTextStyle, 0.0);
+ Blt_Ps_DrawText(ps, string, &axisPtr->limitsTextStyle,
+ vMin, (double)graphPtr->bottom);
+ vMin += (textWidth + SPACING);
+ }
+ }
+ }
+ }
+}
+
+Axis *
+Blt_GetFirstAxis(Blt_Chain chain)
+{
+ Blt_ChainLink link;
+
+ link = Blt_Chain_FirstLink(chain);
+ if (link == NULL) {
+ return NULL;
+ }
+ return Blt_Chain_GetValue(link);
+}
+
+Axis *
+Blt_NearestAxis(Graph *graphPtr, int x, int y)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->axes.table, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Axis *axisPtr;
+
+ axisPtr = Blt_GetHashValue(hPtr);
+ if ((axisPtr->flags & (DELETE_PENDING|HIDE|AXIS_USE)) != AXIS_USE) {
+ continue;
+ }
+ if (axisPtr->flags & AXIS_SHOWTICKS) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(axisPtr->tickLabels); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ TickLabel *labelPtr;
+ Point2d t;
+ double rw, rh;
+ Point2d bbox[5];
+
+ labelPtr = Blt_Chain_GetValue(link);
+ Blt_GetBoundingBox(labelPtr->width, labelPtr->height,
+ axisPtr->tickAngle, &rw, &rh, bbox);
+ t = Blt_AnchorPoint(labelPtr->anchorPos.x,
+ labelPtr->anchorPos.y, rw, rh, axisPtr->tickAnchor);
+ t.x = x - t.x - (rw * 0.5);
+ t.y = y - t.y - (rh * 0.5);
+
+ bbox[4] = bbox[0];
+ if (Blt_PointInPolygon(&t, bbox, 5)) {
+ axisPtr->detail = "label";
+ return axisPtr;
+ }
+ }
+ }
+ if (axisPtr->title != NULL) { /* and then the title string. */
+ Point2d bbox[5];
+ Point2d t;
+ double rw, rh;
+ unsigned int w, h;
+
+ Blt_GetTextExtents(axisPtr->titleFont, 0, axisPtr->title,-1,&w,&h);
+ Blt_GetBoundingBox(w, h, axisPtr->titleAngle, &rw, &rh, bbox);
+ t = Blt_AnchorPoint(axisPtr->titlePos.x, axisPtr->titlePos.y,
+ rw, rh, axisPtr->titleAnchor);
+ /* Translate the point so that the 0,0 is the upper left
+ * corner of the bounding box. */
+ t.x = x - t.x - (rw * 0.5);
+ t.y = y - t.y - (rh * 0.5);
+
+ bbox[4] = bbox[0];
+ if (Blt_PointInPolygon(&t, bbox, 5)) {
+ axisPtr->detail = "title";
+ return axisPtr;
+ }
+ }
+ if (axisPtr->lineWidth > 0) { /* Check for the axis region */
+ if ((x <= axisPtr->right) && (x >= axisPtr->left) &&
+ (y <= axisPtr->bottom) && (y >= axisPtr->top)) {
+ axisPtr->detail = "line";
+ return axisPtr;
+ }
+ }
+ }
+ return NULL;
+}
+
+ClientData
+Blt_MakeAxisTag(Graph *graphPtr, const char *tagName)
+{
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&graphPtr->axes.tagTable, tagName, &isNew);
+ return Blt_GetHashKey(&graphPtr->axes.tagTable, hPtr);
+}
+
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TimeScaleAxis --
+ *
+ * Determine the units of a linear scaled axis.
+ *
+ * The axis limits are either the range of the data values mapped
+ * to the axis (autoscaled), or the values specified by the -min
+ * and -max options (manual).
+ *
+ * If autoscaled, the smallest and largest major ticks will
+ * encompass the range of data values. If the -loose option is
+ * selected, the next outer ticks are choosen. If tight, the
+ * ticks are at or inside of the data limits are used.
+ *
+ * If manually set, the ticks are at or inside the data limits
+ * are used. This makes sense for zooming. You want the
+ * selected range to represent the next limit, not something a
+ * bit bigger.
+ *
+ * Note: I added an "always" value to the -loose option to force
+ * the manually selected axes to be loose. It's probably
+ * not a good idea.
+ *
+ * maxY
+ * | units = magnitude (of least significant digit)
+ * | high = largest unit tick < max axis value
+ * high _| low = smallest unit tick > min axis value
+ * |
+ * | range = high - low
+ * | # ticks = greatest factor of range/units
+ * _|
+ * U |
+ * n |
+ * i |
+ * t _|
+ * |
+ * |
+ * |
+ * low _|
+ * |
+ * |_minX________________maxX__
+ * | | | | |
+ * minY low high
+ * minY
+ *
+ * numTicks = Number of ticks
+ * min = Minimum value of axis
+ * max = Maximum value of axis
+ * range = Range of values (max - min)
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The axis tick information is set. The actual tick values will
+ * be generated later.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+TimeScaleAxis(Axis *axisPtr, double min, double max)
+{
+}
+
+
diff --git a/tlt3.0/bltGrAxis.h b/tlt3.0/bltGrAxis.h
new file mode 100644
index 0000000..a009aec
--- /dev/null
+++ b/tlt3.0/bltGrAxis.h
@@ -0,0 +1,332 @@
+
+/*
+ * bltGrAxis.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GR_AXIS_H
+#define _BLT_GR_AXIS_H
+
+#include "bltList.h"
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Grid --
+ *
+ * Contains attributes of describing how to draw grids (at major ticks)
+ * in the graph. Grids may be mapped to either/both X and Y axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ Blt_Dashes dashes; /* Dash style of the grid. This represents an
+ * array of alternatingly drawn pixel
+ * values. */
+ int lineWidth; /* Width of the grid lines */
+ XColor *color; /* Color of the grid lines */
+ GC gc; /* Graphics context for the grid. */
+
+ Segment2d *segments; /* Array of line segments representing the
+ * grid lines */
+ int nUsed; /* # of axis segments in use. */
+ int nAllocated; /* # of axis segments allocated. */
+} Grid;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AxisRange --
+ *
+ * Designates a range of values by a minimum and maximum limit.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ double min, max, range, scale;
+} AxisRange;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TickLabel --
+ *
+ * Structure containing the X-Y screen coordinates of the tick
+ * label (anchored at its center).
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ Point2d anchorPos;
+ unsigned int width, height;
+ char string[1];
+} TickLabel;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Ticks --
+ *
+ * Structure containing information where the ticks (major or
+ * minor) will be displayed on the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ unsigned int nTicks; /* # of ticks on axis */
+ double values[1]; /* Array of tick values (malloc-ed). */
+} Ticks;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TickSweep --
+ *
+ * Structure containing information where the ticks (major or
+ * minor) will be displayed on the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ double initial; /* Initial value */
+ double step; /* Size of interval */
+ unsigned int nSteps; /* Number of intervals. */
+} TickSweep;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Axis --
+ *
+ * Structure contains options controlling how the axis will be
+ * displayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in axis. */
+
+ unsigned int flags;
+
+ Blt_HashEntry *hashPtr;
+
+ /* Fields specific to axes. */
+
+ const char *detail;
+
+ int refCount; /* Number of elements referencing this
+ * axis. */
+ int logScale; /* If non-zero, generate log scale
+ * ticks for the axis. */
+ int timeScale; /* If non-zero, generate time scale
+ * ticks for the axis. This option is
+ * overridden by -logscale. */
+ int descending; /* If non-zero, display the range of
+ * values on the axis in descending
+ * order, from high to low. */
+
+ int looseMin, looseMax; /* If non-zero, axis range extends to
+ * the outer major ticks, otherwise at
+ * the limits of the data values. This
+ * is overriddened by setting the -min
+ * and -max options. */
+
+ const char *title; /* Title of the axis. */
+
+ int titleAlternate; /* Indicates whether to position the
+ * title above/left of the axis. */
+
+ Point2d titlePos; /* Position of the title */
+
+ unsigned short int titleWidth, titleHeight;
+
+
+ int lineWidth; /* Width of lines representing axis
+ * (including ticks). If zero, then
+ * no axis lines or ticks are
+ * drawn. */
+
+ const char **limitsFormats; /* One or two strings of sprintf-like
+ * formats describing how to display
+ * virtual axis limits. If NULL,
+ * display no limits. */
+ int nFormats;
+
+ TextStyle limitsTextStyle; /* Text attributes (color, font,
+ * rotation, etc.) of the limits. */
+
+ double windowSize; /* Size of a sliding window of values
+ * used to scale the axis
+ * automatically as new data values
+ * are added. The axis will always
+ * display the latest values in this
+ * range. */
+
+ double shiftBy; /* Shift maximum by this interval. */
+
+ int tickLength; /* Length of major ticks in pixels */
+
+ const char *formatCmd; /* Specifies a TCL command, to be
+ * invoked by the axis whenever it has
+ * to generate tick labels. */
+
+ Tcl_Obj *scrollCmdObjPtr;
+ int scrollUnits;
+
+ double min, max; /* The actual axis range. */
+
+ double reqMin, reqMax; /* Requested axis bounds. Consult the
+ * axisPtr->flags field for
+ * AXIS_CONFIG_MIN and AXIS_CONFIG_MAX
+ * to see if the requested bound have
+ * been set. They override the
+ * computed range of the axis
+ * (determined by auto-scaling). */
+
+ double reqScrollMin, reqScrollMax;
+
+ double scrollMin, scrollMax; /* Defines the scrolling reqion of the
+ * axis. Normally the region is
+ * determined from the data limits. If
+ * specified, these values override
+ * the data-range. */
+
+ AxisRange valueRange; /* Range of data values of elements
+ * mapped to this axis. This is used
+ * to auto-scale the axis in "tight"
+ * mode. */
+ AxisRange axisRange; /* Smallest and largest major tick
+ * values for the axis. The tick
+ * values lie outside the range of
+ * data values. This is used to
+ * auto-scale the axis in "loose"
+ * mode. */
+
+ double prevMin, prevMax;
+
+ double reqStep; /* If > 0.0, overrides the computed major
+ * tick interval. Otherwise a stepsize
+ * is automatically calculated, based
+ * upon the range of elements mapped to the
+ * axis. The default value is 0.0. */
+
+ Ticks *t1Ptr; /* Array of major tick positions. May be
+ * set by the user or generated from the
+ * major sweep below. */
+
+ Ticks *t2Ptr; /* Array of minor tick positions. May be
+ * set by the user or generated from the
+ * minor sweep below. */
+
+ TickSweep minorSweep, majorSweep;
+
+ int reqNumMajorTicks; /* Default number of ticks to be displayed. */
+ int reqNumMinorTicks; /* If non-zero, represents the
+ * requested the number of minor ticks
+ * to be uniformally displayed along
+ * each major tick. */
+
+
+ int labelOffset; /* If non-zero, indicates that the tick
+ * label should be offset to sit in the
+ * middle of the next interval. */
+
+ /* The following fields are specific to logical axes */
+
+ int margin; /* Margin that contains this axis. */
+ Blt_ChainLink link; /* Axis link in margin list. */
+ Blt_Chain chain;
+ Segment2d *segments; /* Array of line segments representing
+ * the major and minor ticks, but also
+ * the * axis line itself. The segment
+ * coordinates * are relative to the
+ * axis. */
+ int nSegments; /* Number of segments in the above
+ * array. */
+ Blt_Chain tickLabels; /* Contains major tick label strings
+ * and their offsets along the
+ * axis. */
+ short int left, right, top, bottom; /* Region occupied by the of axis. */
+ short int width, height; /* Extents of axis */
+ short int maxTickWidth, maxTickHeight;
+ Blt_Background normalBg;
+ Blt_Background activeBg;
+ XColor *activeFgColor;
+
+ int relief;
+ int borderWidth;
+ int activeRelief;
+
+ float tickAngle;
+ Blt_Font tickFont;
+ Tk_Anchor tickAnchor;
+ Tk_Anchor reqTickAnchor;
+ XColor *tickColor;
+ GC tickGC; /* Graphics context for axis and tick
+ * labels */
+ GC activeTickGC;
+
+ double titleAngle;
+ Blt_Font titleFont;
+ Tk_Anchor titleAnchor;
+ Tk_Justify titleJustify;
+ XColor *titleColor;
+
+ Grid major, minor; /* Axis grid information. */
+
+ double screenScale;
+ int screenMin, screenRange;
+
+} Axis;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Axis2d --
+ *
+ * The pair of axes mapping a point onto the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ Axis *x, *y;
+} Axis2d;
+
+/* Axis flags: */
+
+#define AXIS_AUTO_MAJOR (1<<16) /* Auto-generate major ticks. */
+#define AXIS_AUTO_MINOR (1<<17) /* Auto-generate minor ticks. */
+#define AXIS_ONSCREEN (1<<18) /* Axis is displayed on the screen via
+ * the "use" operation */
+#define AXIS_GRID (1<<19)
+#define AXIS_GRID_MINOR (1<<20)
+#define AXIS_TICKS (1<<21)
+#define AXIS_TICKS_INTERIOR (1<<22)
+#define AXIS_CHECK_LIMITS (1<<23)
+#define AXIS_LOGSCALE (1<<24)
+#define AXIS_DECREASING (1<<25)
+
+#endif /* _BLT_GR_AXIS_H */
diff --git a/tlt3.0/bltGrBar.c b/tlt3.0/bltGrBar.c
new file mode 100644
index 0000000..0caf5ba
--- /dev/null
+++ b/tlt3.0/bltGrBar.c
@@ -0,0 +1,2539 @@
+
+/*
+ * bltGrBar.c --
+ *
+ * This module implements barchart elements for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltGrElem.h"
+
+#define CLAMP(x,l,h) ((x) = (((x)<(l))? (l) : ((x)>(h)) ? (h) : (x)))
+
+typedef struct {
+ float x1, y1, x2, y2;
+} BarRegion;
+
+typedef struct {
+ Point2f ul, lr;
+ Segment2d segments[4];
+ int nSegments;
+} Bar;
+
+typedef struct {
+ const char *name; /* Pen style identifier. If NULL, pen
+ * was statically allocated. */
+ ClassId classId; /* Type of pen */
+ const char *typeId; /* String token identifying the type of
+ * pen */
+ unsigned int flags; /* Indicates if the pen element is
+ * active or normal */
+ int refCount; /* Reference count for elements using
+ * this pen. */
+ Blt_HashEntry *hashPtr;
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications */
+ PenConfigureProc *configProc;
+ PenDestroyProc *destroyProc;
+ Graph *graphPtr; /* Graph that the pen is associated
+ * with. */
+ /* Barchart specific pen fields start here. */
+ XColor *outlineColor; /* Outline (foreground) color of bar */
+ Blt_Background fill; /* 3D border and fill (background)
+ * color */
+ int borderWidth; /* 3D border width of bar */
+ int relief; /* Relief of the bar */
+ Pixmap stipple; /* Stipple */
+ GC fillGC; /* Graphics context */
+ GC outlineGC; /* GC for outline of bar. */
+
+ /* Error bar attributes. */
+ int errorBarShow; /* Describes which error bars to
+ * display: none, x, y, or * both. */
+
+ int errorBarLineWidth; /* Width of the error bar segments. */
+
+ int errorBarCapWidth;
+ XColor *errorBarColor; /* Color of the error bar. */
+
+ GC errorBarGC; /* Error bar graphics context. */
+
+ /* Show value attributes. */
+ int valueShow; /* Indicates whether to display data
+ * value. Values are x, y, or none. */
+
+ const char *valueFormat; /* A printf format string. */
+ TextStyle valueStyle; /* Text attributes (color, font,
+ * rotation, etc.) of the value. */
+
+} BarPen;
+
+typedef struct {
+ Weight weight; /* Weight range where this pen is
+ * valid. */
+ BarPen *penPtr; /* Pen to use. */
+
+ XRectangle *bars; /* Indicates starting location in bar
+ * array for this pen. */
+ int nBars; /* # of bar segments for this pen. */
+
+ GraphSegments xeb, yeb; /* X and Y error bars. */
+
+ int symbolSize; /* Size of the pen's symbol scaled to
+ * the current graph size. */
+ int errorBarCapWidth; /* Length of the cap ends on each error
+ * bar. */
+
+} BarStyle;
+
+typedef struct {
+ GraphObj obj; /* Must be first field in element. */
+ unsigned int flags;
+ Blt_HashEntry *hashPtr;
+
+ /* Fields specific to elements. */
+ const char *label; /* Label displayed in legend */
+ unsigned short row, col; /* Position of the entry in the
+ * legend. */
+ int legendRelief; /* Relief of label in legend. */
+ Axis2d axes; /* X-axis and Y-axis mapping the
+ * element */
+ ElemValues x, y, w; /* Contains array of floating point
+ * graph coordinate values. Also holds
+ * min/max and the number of
+ * coordinates */
+ int *activeIndices; /* Array of indices (malloc-ed) which
+ * indicate which data points are active
+ * (drawn * with "active" colors). */
+ int nActiveIndices; /* Number of active data points.
+ * Special case: if nActiveIndices < 0
+ * and the active bit is set in "flags",
+ * then all data * points are drawn
+ * active. */
+ ElementProcs *procsPtr;
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications. */
+ BarPen *activePenPtr; /* Standard Pens */
+ BarPen *normalPenPtr;
+ BarPen *builtinPenPtr;
+ Blt_Chain stylePalette; /* Palette of pens. */
+
+ /* Symbol scaling */
+ int scaleSymbols; /* If non-zero, the symbols will scale
+ * in size as the graph is zoomed
+ * in/out. */
+ double xRange, yRange; /* Initial X-axis and Y-axis ranges:
+ * used to scale the size of element's
+ * symbol. */
+ int state;
+ Blt_ChainLink link;
+
+ /* Fields specific to the barchart element */
+
+ float barWidth;
+ const char *groupName;
+
+ int *barToData;
+ XRectangle *bars; /* Array of rectangles comprising the bar
+ * segments of the element. */
+ int *activeToData;
+ XRectangle *activeRects;
+
+ int nBars; /* # of visible bar segments for
+ * element */
+ int nActive;
+
+ int xPad; /* Spacing on either side of bar */
+
+ ElemValues xError; /* Relative/symmetric X error values. */
+ ElemValues yError; /* Relative/symmetric Y error values. */
+ ElemValues xHigh, xLow; /* Absolute/asymmetric X-coordinate
+ * high/low error values. */
+ ElemValues yHigh, yLow; /* Absolute/asymmetric Y-coordinate
+ * high/low error values. */
+ BarPen builtinPen;
+
+ GraphSegments xeb, yeb;
+
+ int errorBarCapWidth; /* Length of cap on error bars */
+} BarElement;
+
+extern Blt_CustomOption bltBarPenOption;
+extern Blt_CustomOption bltValuesOption;
+extern Blt_CustomOption bltValuePairsOption;
+extern Blt_CustomOption bltXAxisOption;
+extern Blt_CustomOption bltYAxisOption;
+extern Blt_CustomOption bltColorOption;
+extern Blt_CustomOption bltBarStylesOption;
+
+static Blt_OptionParseProc ObjToBarMode;
+static Blt_OptionPrintProc BarModeToObj;
+Blt_CustomOption bltBarModeOption =
+{
+ ObjToBarMode, BarModeToObj, NULL, (ClientData)0
+};
+
+#define DEF_BAR_ACTIVE_PEN "activeBar"
+#define DEF_BAR_AXIS_X "x"
+#define DEF_BAR_AXIS_Y "y"
+#define DEF_BAR_BACKGROUND "navyblue"
+#define DEF_BAR_BORDERWIDTH "2"
+#define DEF_BAR_ERRORBAR_COLOR "defcolor"
+#define DEF_BAR_ERRORBAR_LINE_WIDTH "1"
+#define DEF_BAR_ERRORBAR_CAP_WIDTH "1"
+#define DEF_BAR_FOREGROUND "blue"
+#define DEF_BAR_HIDE "no"
+#define DEF_BAR_LABEL_RELIEF "flat"
+#define DEF_BAR_NORMAL_STIPPLE ""
+#define DEF_BAR_RELIEF "raised"
+#define DEF_BAR_SHOW_ERRORBARS "both"
+#define DEF_BAR_STATE "normal"
+#define DEF_BAR_STACK (char *)NULL
+#define DEF_BAR_STYLES ""
+#define DEF_BAR_TAGS "all"
+#define DEF_BAR_WIDTH "0.0"
+
+#define DEF_PEN_ACTIVE_BACKGROUND "red"
+#define DEF_PEN_ACTIVE_FOREGROUND "pink"
+#define DEF_PEN_BORDERWIDTH "2"
+#define DEF_PEN_NORMAL_BACKGROUND "navyblue"
+#define DEF_PEN_NORMAL_FOREGROUND "blue"
+#define DEF_PEN_RELIEF "raised"
+#define DEF_PEN_STIPPLE ""
+#define DEF_PEN_TYPE "bar"
+#define DEF_PEN_VALUE_ANCHOR "s"
+#define DEF_PEN_VALUE_COLOR RGB_BLACK
+#define DEF_PEN_VALUE_FONT STD_FONT_SMALL
+#define DEF_PEN_VALUE_FORMAT "%g"
+#define DEF_PEN_SHOW_VALUES "no"
+
+static Blt_ConfigSpec barPenConfigSpecs[] =
+{
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_PEN_ACTIVE_BACKGROUND, Blt_Offset(BarPen, fill),
+ BLT_CONFIG_NULL_OK | ACTIVE_PEN},
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_PEN_NORMAL_BACKGROUND, Blt_Offset(BarPen, fill),
+ BLT_CONFIG_NULL_OK | NORMAL_PEN},
+ {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL,
+ (char *)NULL, 0, ALL_PENS},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL,
+ (char *)NULL, 0, ALL_PENS},
+ {BLT_CONFIG_PIXELS_NNEG, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_PEN_BORDERWIDTH, Blt_Offset(BarPen, borderWidth), ALL_PENS},
+ {BLT_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
+ DEF_BAR_ERRORBAR_COLOR, Blt_Offset(BarPen, errorBarColor), ALL_PENS,
+ &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarwidth", "errorBarWidth","ErrorBarWidth",
+ DEF_BAR_ERRORBAR_LINE_WIDTH, Blt_Offset(BarPen, errorBarLineWidth),
+ ALL_PENS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarcap", "errorBarCap", "ErrorBarCap",
+ DEF_BAR_ERRORBAR_CAP_WIDTH, Blt_Offset(BarPen, errorBarCapWidth),
+ ALL_PENS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL,
+ (char *)NULL, 0, ALL_PENS},
+ {BLT_CONFIG_SYNONYM, "-fill", "background", (char *)NULL,
+ (char *)NULL, 0, ALL_PENS},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_PEN_ACTIVE_FOREGROUND, Blt_Offset(BarPen, outlineColor),
+ ACTIVE_PEN | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_PEN_NORMAL_FOREGROUND, Blt_Offset(BarPen, outlineColor),
+ NORMAL_PEN | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char *)NULL,
+ (char *)NULL, 0, ALL_PENS},
+ {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief",
+ DEF_PEN_RELIEF, Blt_Offset(BarPen, relief), ALL_PENS},
+ {BLT_CONFIG_FILL, "-showerrorbars", "showErrorBars", "ShowErrorBars",
+ DEF_BAR_SHOW_ERRORBARS, Blt_Offset(BarPen, errorBarShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FILL, "-showvalues", "showValues", "ShowValues",
+ DEF_PEN_SHOW_VALUES, Blt_Offset(BarPen, valueShow),
+ ALL_PENS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMAP, "-stipple", "stipple", "Stipple", DEF_PEN_STIPPLE,
+ Blt_Offset(BarPen, stipple), ALL_PENS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-type", (char *)NULL, (char *)NULL, DEF_PEN_TYPE,
+ Blt_Offset(BarPen, typeId), ALL_PENS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
+ DEF_PEN_VALUE_ANCHOR, Blt_Offset(BarPen, valueStyle.anchor),
+ ALL_PENS},
+ {BLT_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
+ DEF_PEN_VALUE_COLOR, Blt_Offset(BarPen, valueStyle.color),
+ ALL_PENS},
+ {BLT_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
+ DEF_PEN_VALUE_FONT, Blt_Offset(BarPen, valueStyle.font),
+ ALL_PENS},
+ {BLT_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
+ DEF_PEN_VALUE_FORMAT, Blt_Offset(BarPen, valueFormat),
+ ALL_PENS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_FLOAT, "-valuerotate", "valueRotate", "ValueRotate",
+ (char *)NULL, Blt_Offset(BarPen, valueStyle.angle), ALL_PENS},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+
+static Blt_ConfigSpec barElemConfigSpecs[] = {
+ {BLT_CONFIG_CUSTOM, "-activepen", "activePen", "ActivePen",
+ DEF_BAR_ACTIVE_PEN, Blt_Offset(BarElement, activePenPtr),
+ BLT_CONFIG_NULL_OK, &bltBarPenOption},
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_BAR_BACKGROUND, Blt_Offset(BarElement, builtinPen.fill),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_FLOAT, "-barwidth", "barWidth", "BarWidth",
+ DEF_BAR_WIDTH, Blt_Offset(BarElement, barWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_BAR_TAGS,
+ Blt_Offset(BarElement, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_NNEG, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_BAR_BORDERWIDTH, Blt_Offset(BarElement, builtinPen.borderWidth), 0},
+ {BLT_CONFIG_SYNONYM, "-color", "background", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
+ DEF_BAR_ERRORBAR_COLOR,
+ Blt_Offset(BarElement, builtinPen.errorBarColor), 0, &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG,"-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
+ DEF_BAR_ERRORBAR_LINE_WIDTH,
+ Blt_Offset(BarElement, builtinPen.errorBarLineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarcap", "errorBarCap", "ErrorBarCap",
+ DEF_BAR_ERRORBAR_CAP_WIDTH,
+ Blt_Offset(BarElement, builtinPen.errorBarCapWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-data", "data", "Data", (char *)NULL, 0, 0,
+ &bltValuePairsOption},
+ {BLT_CONFIG_SYNONYM, "-fill", "background", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_BAR_FOREGROUND, Blt_Offset(BarElement, builtinPen.outlineColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-label", "label", "Label", (char *)NULL,
+ Blt_Offset(BarElement, label), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_RELIEF, "-legendrelief", "legendRelief", "LegendRelief",
+ DEF_BAR_LABEL_RELIEF, Blt_Offset(BarElement, legendRelief),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_BAR_HIDE,
+ Blt_Offset(BarElement, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_BAR_AXIS_X,
+ Blt_Offset(BarElement, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_BAR_AXIS_Y,
+ Blt_Offset(BarElement, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char *)NULL,
+ (char *)NULL, 0, 0},
+ {BLT_CONFIG_CUSTOM, "-pen", "pen", "Pen", (char *)NULL,
+ Blt_Offset(BarElement, normalPenPtr), BLT_CONFIG_NULL_OK,
+ &bltBarPenOption},
+ {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief",
+ DEF_BAR_RELIEF, Blt_Offset(BarElement, builtinPen.relief), 0},
+ {BLT_CONFIG_FILL, "-showerrorbars", "showErrorBars", "ShowErrorBars",
+ DEF_BAR_SHOW_ERRORBARS, Blt_Offset(BarElement, builtinPen.errorBarShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FILL, "-showvalues", "showValues", "ShowValues",
+ DEF_PEN_SHOW_VALUES, Blt_Offset(BarElement, builtinPen.valueShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-stack", "stack", "Stack", DEF_BAR_STACK,
+ Blt_Offset(BarElement, groupName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_BAR_STATE,
+ Blt_Offset(BarElement, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMAP, "-stipple", "stipple", "Stipple",
+ DEF_BAR_NORMAL_STIPPLE, Blt_Offset(BarElement, builtinPen.stipple),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-styles", "styles", "Styles", DEF_BAR_STYLES,
+ Blt_Offset(BarElement, stylePalette), 0, &bltBarStylesOption},
+ {BLT_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
+ DEF_PEN_VALUE_ANCHOR,
+ Blt_Offset(BarElement, builtinPen.valueStyle.anchor), 0},
+ {BLT_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
+ DEF_PEN_VALUE_COLOR,
+ Blt_Offset(BarElement, builtinPen.valueStyle.color), 0},
+ {BLT_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
+ DEF_PEN_VALUE_FONT,
+ Blt_Offset(BarElement, builtinPen.valueStyle.font), 0},
+ {BLT_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
+ DEF_PEN_VALUE_FORMAT, Blt_Offset(BarElement, builtinPen.valueFormat),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_FLOAT, "-valuerotate", "valueRotate", "ValueRotate",
+ (char *)NULL, Blt_Offset(BarElement, builtinPen.valueStyle.angle), 0},
+ {BLT_CONFIG_CUSTOM, "-weights", "weights", "Weights", (char *)NULL,
+ Blt_Offset(BarElement, w), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-x", "xdata", "Xdata", (char *)NULL,
+ Blt_Offset(BarElement, x), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-y", "ydata", "Ydata", (char *)NULL,
+ Blt_Offset(BarElement, y), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xdata", "xdata", "Xdata", (char *)NULL,
+ Blt_Offset(BarElement, x), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-ydata", "ydata", "Ydata", (char *)NULL,
+ Blt_Offset(BarElement, y), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xerror", "xError", "XError", (char *)NULL,
+ Blt_Offset(BarElement, xError), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xhigh", "xHigh", "XHigh", (char *)NULL,
+ Blt_Offset(BarElement, xHigh), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xlow", "xLow", "XLow", (char *)NULL,
+ Blt_Offset(BarElement, xLow), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-yerror", "yError", "YError", (char *)NULL,
+ Blt_Offset(BarElement, yError), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-yhigh", "yHigh", "YHigh", (char *)NULL,
+ Blt_Offset(BarElement, yHigh), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-ylow", "yLow", "YLow", (char *)NULL,
+ Blt_Offset(BarElement, yLow), 0, &bltValuesOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+/* Forward declarations */
+static PenConfigureProc ConfigureBarPenProc;
+static PenDestroyProc DestroyBarPenProc;
+static ElementClosestProc ClosestBarProc;
+static ElementConfigProc ConfigureBarProc;
+static ElementDestroyProc DestroyBarProc;
+static ElementDrawProc DrawActiveBarProc;
+static ElementDrawProc DrawNormalBarProc;
+static ElementDrawSymbolProc DrawSymbolProc;
+static ElementExtentsProc GetBarExtentsProc;
+static ElementToPostScriptProc ActiveBarToPostScriptProc;
+static ElementToPostScriptProc NormalBarToPostScriptProc;
+static ElementSymbolToPostScriptProc SymbolToPostScriptProc;
+static ElementMapProc MapBarProc;
+
+/*
+ *---------------------------------------------------------------------------
+ * Custom option parse and print procedures
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NameOfBarMode --
+ *
+ * Converts the integer representing the mode style into a string.
+ *
+ *---------------------------------------------------------------------------
+ */
+static const char *
+NameOfBarMode(BarMode mode)
+{
+ switch (mode) {
+ case BARS_INFRONT:
+ return "infront";
+ case BARS_OVERLAP:
+ return "overlap";
+ case BARS_STACKED:
+ return "stacked";
+ case BARS_ALIGNED:
+ return "aligned";
+ default:
+ return "unknown mode value";
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToMode --
+ *
+ * Converts the mode string into its numeric representation.
+ *
+ * Valid mode strings are:
+ *
+ * "infront" Draw a full bar at each point in the element.
+ *
+ * "stacked" Stack bar segments vertically. Each stack is defined
+ * by each ordinate at a particular abscissa. The height
+ * of each segment is represented by the sum the previous
+ * ordinates.
+ *
+ * "aligned" Align bar segments as smaller slices one next to
+ * the other. Like "stacks", aligned segments are
+ * defined by each ordinate at a particular abscissa.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToBarMode(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* Mode style string */
+ char *widgRec, /* Cubicle structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ BarMode *modePtr = (BarMode *)(widgRec + offset);
+ int length;
+ char c;
+ char *string;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "normal", length) == 0)) {
+ *modePtr = BARS_INFRONT;
+ } else if ((c == 'i') && (strncmp(string, "infront", length) == 0)) {
+ *modePtr = BARS_INFRONT;
+ } else if ((c == 's') && (strncmp(string, "stacked", length) == 0)) {
+ *modePtr = BARS_STACKED;
+ } else if ((c == 'a') && (strncmp(string, "aligned", length) == 0)) {
+ *modePtr = BARS_ALIGNED;
+ } else if ((c == 'o') && (strncmp(string, "overlap", length) == 0)) {
+ *modePtr = BARS_OVERLAP;
+ } else {
+ Tcl_AppendResult(interp, "bad mode argument \"", string, "\": should"
+ "be \"infront\", \"stacked\", \"overlap\", or \"aligned\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BarModeToObj --
+ *
+ * Returns the mode style string based upon the mode flags.
+ *
+ * Results:
+ * The mode style string is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+BarModeToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Row/column structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ BarMode mode = *(BarMode *)(widgRec + offset);
+
+ return Tcl_NewStringObj(NameOfBarMode(mode), -1);
+}
+
+
+/*
+ * Zero out the style's number of bars and errorbars.
+ */
+static void
+ResetStylePalette(Blt_Chain stylePalette)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->xeb.length = stylePtr->yeb.length = 0;
+ stylePtr->nBars = 0;
+ }
+}
+
+static int
+ConfigureBarPen(Graph *graphPtr, BarPen *penPtr)
+{
+ XGCValues gcValues;
+ unsigned long gcMask;
+ GC newGC;
+ long defColor;
+ int screenNum;
+
+ screenNum = Tk_ScreenNumber(graphPtr->tkwin);
+ gcMask = GCForeground | GCLineWidth;
+ gcValues.line_width = LineWidth(penPtr->errorBarLineWidth);
+
+ if (penPtr->outlineColor != NULL) {
+ defColor = penPtr->outlineColor->pixel;
+ gcValues.foreground = penPtr->outlineColor->pixel;
+ } else if (penPtr->fill != NULL) {
+ defColor = Blt_BackgroundBorderColor(penPtr->fill)->pixel;
+ gcValues.foreground = defColor;
+ } else {
+ defColor = BlackPixel(graphPtr->display, screenNum);
+ }
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (penPtr->outlineGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->outlineGC);
+ }
+ penPtr->outlineGC = newGC;
+
+ newGC = NULL;
+ if (penPtr->stipple != None) {
+ /* Handle old-style -stipple specially. */
+ gcMask = GCForeground | GCBackground | GCFillStyle | GCStipple;
+ gcValues.foreground = BlackPixel(graphPtr->display, screenNum);
+ gcValues.background = WhitePixel(graphPtr->display, screenNum);
+ if (penPtr->fill != NULL) {
+ gcValues.foreground =
+ Blt_BackgroundBorderColor(penPtr->fill)->pixel;
+ } else if (penPtr->outlineColor != NULL) {
+ gcValues.foreground = penPtr->outlineColor->pixel;
+ }
+ gcValues.stipple = penPtr->stipple;
+ gcValues.fill_style = FillStippled;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ }
+ if (penPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->fillGC);
+ }
+ penPtr->fillGC = newGC;
+
+ gcMask = GCForeground | GCLineWidth;
+ if (penPtr->errorBarColor == COLOR_DEFAULT) {
+ gcValues.foreground = defColor;
+ } else {
+ gcValues.foreground = penPtr->errorBarColor->pixel;
+ }
+ gcValues.line_width = LineWidth(penPtr->errorBarLineWidth);
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (penPtr->errorBarGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->errorBarGC);
+ }
+ penPtr->errorBarGC = newGC;
+ return TCL_OK;
+}
+
+static void
+DestroyBarPen(Graph *graphPtr, BarPen *penPtr)
+{
+ Blt_Ts_FreeStyle(graphPtr->display, &penPtr->valueStyle);
+ if (penPtr->outlineGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->outlineGC);
+ }
+ if (penPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->fillGC);
+ }
+ if (penPtr->errorBarGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->errorBarGC);
+ }
+}
+
+static int
+ConfigureBarPenProc(Graph *graphPtr, Pen *basePtr)
+{
+ return ConfigureBarPen(graphPtr, (BarPen *)basePtr);
+}
+
+static void
+DestroyBarPenProc(Graph *graphPtr, Pen *basePtr)
+{
+ DestroyBarPen(graphPtr, (BarPen *)basePtr);
+}
+
+
+static void
+InitializeBarPen(BarPen *penPtr)
+{
+ /* Generic fields common to all pen types. */
+ penPtr->configProc = ConfigureBarPenProc;
+ penPtr->destroyProc = DestroyBarPenProc;
+ penPtr->flags = NORMAL_PEN;
+ penPtr->configSpecs = barPenConfigSpecs;
+
+ /* Initialize fields specific to bar pens. */
+ Blt_Ts_InitStyle(penPtr->valueStyle);
+ penPtr->relief = TK_RELIEF_RAISED;
+ penPtr->valueShow = SHOW_NONE;
+ penPtr->borderWidth = 2;
+ penPtr->errorBarShow = SHOW_BOTH;
+}
+
+Pen *
+Blt_BarPen(const char *penName)
+{
+ BarPen *penPtr;
+
+ penPtr = calloc(1, sizeof(BarPen));
+ InitializeBarPen(penPtr);
+ penPtr->name = Blt_Strdup(penName);
+ if (strcmp(penName, "activeBar") == 0) {
+ penPtr->flags = ACTIVE_PEN;
+ }
+ return (Pen *)penPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CheckBarStacks --
+ *
+ * Check that the data limits are not superseded by the heights of
+ * stacked bar segments. The heights are calculated by
+ * Blt_ComputeStacks.
+ *
+ * Results:
+ * If the y-axis limits need to be adjusted for stacked segments,
+ * *minPtr* or *maxPtr* are updated.
+ *
+ * Side effects:
+ * Autoscaling of the y-axis is affected.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+CheckBarStacks(Graph *graphPtr, Axis2d *pairPtr, double *minPtr, double *maxPtr)
+{
+ BarGroup *gp, *gend;
+
+ if ((graphPtr->mode != BARS_STACKED) || (graphPtr->nBarGroups == 0)) {
+ return;
+ }
+ for (gp = graphPtr->barGroups, gend = gp + graphPtr->nBarGroups; gp < gend;
+ gp++) {
+ if ((gp->axes.x == pairPtr->x) && (gp->axes.y == pairPtr->y)) {
+ /*
+ * Check if any of the y-values (because of stacking) are greater
+ * than the current limits of the graph.
+ */
+ if (gp->sum < 0.0f) {
+ if (*minPtr > gp->sum) {
+ *minPtr = gp->sum;
+ }
+ } else {
+ if (*maxPtr < gp->sum) {
+ *maxPtr = gp->sum;
+ }
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureBarProc --
+ *
+ * Sets up the appropriate configuration parameters in the GC. It is
+ * assumed the parameters have been previously set by a call to
+ * Blt_ConfigureWidget.
+ *
+ * Results:
+ * The return value is a standard TCL result. If TCL_ERROR is returned,
+ * then interp->result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as bar foreground/background color and
+ * stipple etc. get set in a new GC.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ConfigureBarProc(Graph *graphPtr, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ Blt_ChainLink link;
+ BarStyle *stylePtr;
+
+ if (ConfigureBarPen(graphPtr, elemPtr->builtinPenPtr)!= TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Point to the static normal pen if no external pens have been selected.
+ */
+ link = Blt_Chain_FirstLink(elemPtr->stylePalette);
+ if (link == NULL) {
+ link = Blt_Chain_AllocLink(sizeof(BarStyle));
+ Blt_Chain_LinkAfter(elemPtr->stylePalette, link, NULL);
+ }
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->penPtr = NORMALPEN(elemPtr);
+
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-barwidth", "-*data",
+ "-map*", "-label", "-hide", "-x", "-y", (char *)NULL)) {
+ elemPtr->flags |= MAP_ITEM;
+ }
+ return TCL_OK;
+}
+
+static void
+GetBarExtentsProc(Element *basePtr, Region2d *regPtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ Graph *graphPtr;
+ double middle, barWidth;
+ int nPoints;
+
+ graphPtr = elemPtr->obj.graphPtr;
+ regPtr->top = regPtr->left = DBL_MAX;
+ regPtr->bottom = regPtr->right = -DBL_MAX;
+
+ nPoints = NUMBEROFPOINTS(elemPtr);
+ if (nPoints < 1) {
+ return; /* No data points */
+ }
+ barWidth = graphPtr->barWidth;
+ if (elemPtr->barWidth > 0.0f) {
+ barWidth = elemPtr->barWidth;
+ }
+ middle = 0.5;
+ regPtr->left = elemPtr->x.min - middle;
+ regPtr->right = elemPtr->x.max + middle;
+
+ regPtr->top = elemPtr->y.min;
+ regPtr->bottom = elemPtr->y.max;
+ if (regPtr->bottom < graphPtr->baseline) {
+ regPtr->bottom = graphPtr->baseline;
+ }
+ /*
+ * Handle stacked bar elements specially.
+ *
+ * If element is stacked, the sum of its ordinates may be outside the
+ * minimum/maximum limits of the element's data points.
+ */
+ if ((graphPtr->mode == BARS_STACKED) && (graphPtr->nBarGroups > 0)) {
+ CheckBarStacks(graphPtr, &elemPtr->axes, ®Ptr->top, ®Ptr->bottom);
+ }
+ /* Warning: You get what you deserve if the x-axis is logScale */
+ if (elemPtr->axes.x->logScale) {
+ regPtr->left = Blt_FindElemValuesMinimum(&elemPtr->x, DBL_MIN) +
+ middle;
+ }
+ /* Fix y-min limits for barchart */
+ if (elemPtr->axes.y->logScale) {
+ if ((regPtr->top <= 0.0) || (regPtr->top > 1.0)) {
+ regPtr->top = 1.0;
+ }
+ } else {
+ if (regPtr->top > 0.0) {
+ regPtr->top = 0.0;
+ }
+ }
+ /* Correct the extents for error bars if they exist. */
+ if (elemPtr->xError.nValues > 0) {
+ int i;
+
+ /* Correct the data limits for error bars */
+ nPoints = MIN(elemPtr->xError.nValues, nPoints);
+ for (i = 0; i < nPoints; i++) {
+ double x;
+
+ x = elemPtr->x.values[i] + elemPtr->xError.values[i];
+ if (x > regPtr->right) {
+ regPtr->right = x;
+ }
+ x = elemPtr->x.values[i] - elemPtr->xError.values[i];
+ if (elemPtr->axes.x->logScale) {
+ if (x < 0.0) {
+ x = -x; /* Mirror negative values, instead of
+ * ignoring them. */
+ }
+ if ((x > DBL_MIN) && (x < regPtr->left)) {
+ regPtr->left = x;
+ }
+ } else if (x < regPtr->left) {
+ regPtr->left = x;
+ }
+ }
+ } else {
+ if ((elemPtr->xHigh.nValues > 0) &&
+ (elemPtr->xHigh.max > regPtr->right)) {
+ regPtr->right = elemPtr->xHigh.max;
+ }
+ if (elemPtr->xLow.nValues > 0) {
+ double left;
+
+ if ((elemPtr->xLow.min <= 0.0) &&
+ (elemPtr->axes.x->logScale)) {
+ left = Blt_FindElemValuesMinimum(&elemPtr->xLow, DBL_MIN);
+ } else {
+ left = elemPtr->xLow.min;
+ }
+ if (left < regPtr->left) {
+ regPtr->left = left;
+ }
+ }
+ }
+ if (elemPtr->yError.nValues > 0) {
+ int i;
+
+ nPoints = MIN(elemPtr->yError.nValues, nPoints);
+ for (i = 0; i < nPoints; i++) {
+ double y;
+
+ y = elemPtr->y.values[i] + elemPtr->yError.values[i];
+ if (y > regPtr->bottom) {
+ regPtr->bottom = y;
+ }
+ y = elemPtr->y.values[i] - elemPtr->yError.values[i];
+ if (elemPtr->axes.y->logScale) {
+ if (y < 0.0) {
+ y = -y; /* Mirror negative values, instead of
+ * ignoring them. */
+ }
+ if ((y > DBL_MIN) && (y < regPtr->left)) {
+ regPtr->top = y;
+ }
+ } else if (y < regPtr->top) {
+ regPtr->top = y;
+ }
+ }
+ } else {
+ if ((elemPtr->yHigh.nValues > 0) &&
+ (elemPtr->yHigh.max > regPtr->bottom)) {
+ regPtr->bottom = elemPtr->yHigh.max;
+ }
+ if (elemPtr->yLow.nValues > 0) {
+ double top;
+
+ if ((elemPtr->yLow.min <= 0.0) &&
+ (elemPtr->axes.y->logScale)) {
+ top = Blt_FindElemValuesMinimum(&elemPtr->yLow, DBL_MIN);
+ } else {
+ top = elemPtr->yLow.min;
+ }
+ if (top < regPtr->top) {
+ regPtr->top = top;
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClosestBar --
+ *
+ * Find the bar segment closest to the window coordinates point
+ * specified.
+ *
+ * Note: This does not return the height of the stacked segment
+ * (in graph coordinates) properly.
+ *
+ * Results:
+ * Returns 1 if the point is width any bar segment, otherwise 0.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+ClosestBarProc(
+ Graph *graphPtr, /* Not used. */
+ Element *basePtr, /* Bar element */
+ ClosestSearch *searchPtr) /* Information about closest point in
+ * element */
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ XRectangle *bp;
+ double minDist;
+ int imin;
+ int i;
+
+ minDist = searchPtr->dist;
+ imin = 0;
+
+ for (bp = elemPtr->bars, i = 0; i < elemPtr->nBars; i++, bp++) {
+ Point2d *pp, *pend;
+ Point2d outline[5];
+ double left, right, top, bottom;
+
+ if (PointInRectangle(bp, searchPtr->x, searchPtr->y)) {
+ imin = elemPtr->barToData[i];
+ minDist = 0.0;
+ break;
+ }
+ left = bp->x, top = bp->y;
+ right = (double)(bp->x + bp->width);
+ bottom = (double)(bp->y + bp->height);
+ outline[4].x = outline[3].x = outline[0].x = left;
+ outline[4].y = outline[1].y = outline[0].y = top;
+ outline[2].x = outline[1].x = right;
+ outline[3].y = outline[2].y = bottom;
+
+ for (pp = outline, pend = outline + 4; pp < pend; pp++) {
+ Point2d t;
+ double dist;
+
+ t = Blt_GetProjection(searchPtr->x, searchPtr->y, pp, pp + 1);
+ if (t.x > right) {
+ t.x = right;
+ } else if (t.x < left) {
+ t.x = left;
+ }
+ if (t.y > bottom) {
+ t.y = bottom;
+ } else if (t.y < top) {
+ t.y = top;
+ }
+ dist = hypot((t.x - searchPtr->x), (t.y - searchPtr->y));
+ if (dist < minDist) {
+ minDist = dist;
+ imin = elemPtr->barToData[i];
+ }
+ }
+ }
+ if (minDist < searchPtr->dist) {
+ searchPtr->elemPtr = (Element *)elemPtr;
+ searchPtr->dist = minDist;
+ searchPtr->index = imin;
+ searchPtr->point.x = (double)elemPtr->x.values[imin];
+ searchPtr->point.y = (double)elemPtr->y.values[imin];
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MergePens --
+ *
+ * Reorders the both arrays of points and errorbars to merge pens.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old arrays are freed and new ones allocated containing
+ * the reordered points and errorbars.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MergePens(BarElement *elemPtr, BarStyle **dataToStyle)
+{
+ if (Blt_Chain_GetLength(elemPtr->stylePalette) < 2) {
+ Blt_ChainLink link;
+ BarStyle *stylePtr;
+
+ link = Blt_Chain_FirstLink(elemPtr->stylePalette);
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->nBars = elemPtr->nBars;
+ stylePtr->bars = elemPtr->bars;
+ stylePtr->symbolSize = elemPtr->bars->width / 2;
+ stylePtr->xeb.length = elemPtr->xeb.length;
+ stylePtr->xeb.segments = elemPtr->xeb.segments;
+ stylePtr->yeb.length = elemPtr->yeb.length;
+ stylePtr->yeb.segments = elemPtr->yeb.segments;
+ return;
+ }
+ /* We have more than one style. Group bar segments of like pen styles
+ * together. */
+
+ if (elemPtr->nBars > 0) {
+ Blt_ChainLink link;
+ XRectangle *bars, *bp;
+ int *ip, *barToData;
+
+ bars = malloc(elemPtr->nBars * sizeof(XRectangle));
+ barToData = malloc(elemPtr->nBars * sizeof(int));
+ bp = bars, ip = barToData;
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->symbolSize = bp->width / 2;
+ stylePtr->bars = bp;
+ for (i = 0; i < elemPtr->nBars; i++) {
+ int iData;
+
+ iData = elemPtr->barToData[i];
+ if (dataToStyle[iData] == stylePtr) {
+ *bp++ = elemPtr->bars[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->nBars = bp - stylePtr->bars;
+ }
+ free(elemPtr->bars);
+ free(elemPtr->barToData);
+ elemPtr->bars = bars;
+ elemPtr->barToData = barToData;
+ }
+
+ if (elemPtr->xeb.length > 0) {
+ Blt_ChainLink link;
+ Segment2d *bars, *sp;
+ int *map, *ip;
+
+ bars = malloc(elemPtr->xeb.length * sizeof(Segment2d));
+ map = malloc(elemPtr->xeb.length * sizeof(int));
+ sp = bars, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->xeb.segments = sp;
+ for (i = 0; i < elemPtr->xeb.length; i++) {
+ int iData;
+
+ iData = elemPtr->xeb.map[i];
+ if (dataToStyle[iData] == stylePtr) {
+ *sp++ = elemPtr->xeb.segments[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->xeb.length = sp - stylePtr->xeb.segments;
+ }
+ free(elemPtr->xeb.segments);
+ elemPtr->xeb.segments = bars;
+ free(elemPtr->xeb.map);
+ elemPtr->xeb.map = map;
+ }
+ if (elemPtr->yeb.length > 0) {
+ Blt_ChainLink link;
+ Segment2d *bars, *sp;
+ int *map, *ip;
+
+ bars = malloc(elemPtr->yeb.length * sizeof(Segment2d));
+ map = malloc(elemPtr->yeb.length * sizeof(int));
+ sp = bars, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->yeb.segments = sp;
+ for (i = 0; i < elemPtr->yeb.length; i++) {
+ int iData;
+
+ iData = elemPtr->yeb.map[i];
+ if (dataToStyle[iData] == stylePtr) {
+ *sp++ = elemPtr->yeb.segments[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->yeb.length = sp - stylePtr->yeb.segments;
+ }
+ free(elemPtr->yeb.segments);
+ elemPtr->yeb.segments = bars;
+ free(elemPtr->yeb.map);
+ elemPtr->yeb.map = map;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapActiveBars --
+ *
+ * Creates an array of points of the active graph coordinates.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the active point array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapActiveBars(BarElement *elemPtr)
+{
+ if (elemPtr->activeRects != NULL) {
+ free(elemPtr->activeRects);
+ elemPtr->activeRects = NULL;
+ }
+ if (elemPtr->activeToData != NULL) {
+ free(elemPtr->activeToData);
+ elemPtr->activeToData = NULL;
+ }
+ elemPtr->nActive = 0;
+
+ if (elemPtr->nActiveIndices > 0) {
+ XRectangle *activeRects;
+ int *activeToData;
+ int i;
+ int count;
+
+ activeRects = malloc(sizeof(XRectangle) *
+ elemPtr->nActiveIndices);
+ activeToData = malloc(sizeof(int) *
+ elemPtr->nActiveIndices);
+ count = 0;
+ for (i = 0; i < elemPtr->nBars; i++) {
+ int *ip, *iend;
+
+ for (ip = elemPtr->activeIndices,
+ iend = ip + elemPtr->nActiveIndices; ip < iend; ip++) {
+ if (elemPtr->barToData[i] == *ip) {
+ activeRects[count] = elemPtr->bars[i];
+ activeToData[count] = i;
+ count++;
+ }
+ }
+ }
+ elemPtr->nActive = count;
+ elemPtr->activeRects = activeRects;
+ elemPtr->activeToData = activeToData;
+ }
+ elemPtr->flags &= ~ACTIVE_PENDING;
+}
+
+static void
+ResetBar(BarElement *elemPtr)
+{
+ /* Release any storage associated with the display of the bar */
+ ResetStylePalette(elemPtr->stylePalette);
+ if (elemPtr->activeRects != NULL) {
+ free(elemPtr->activeRects);
+ }
+ if (elemPtr->activeToData != NULL) {
+ free(elemPtr->activeToData);
+ }
+ if (elemPtr->xeb.segments != NULL) {
+ free(elemPtr->xeb.segments);
+ }
+ if (elemPtr->xeb.map != NULL) {
+ free(elemPtr->xeb.map);
+ }
+ if (elemPtr->yeb.segments != NULL) {
+ free(elemPtr->yeb.segments);
+ }
+ if (elemPtr->yeb.map != NULL) {
+ free(elemPtr->yeb.map);
+ }
+ if (elemPtr->bars != NULL) {
+ free(elemPtr->bars);
+ }
+ if (elemPtr->barToData != NULL) {
+ free(elemPtr->barToData);
+ }
+ elemPtr->activeToData = elemPtr->xeb.map = elemPtr->yeb.map =
+ elemPtr->barToData = NULL;
+ elemPtr->activeRects = elemPtr->bars = NULL;
+ elemPtr->xeb.segments = elemPtr->yeb.segments = NULL;
+ elemPtr->nActive = elemPtr->xeb.length = elemPtr->yeb.length =
+ elemPtr->nBars = 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_MapErrorBars --
+ *
+ * Creates two arrays of points and pen indices, filled with the screen
+ * coordinates of the visible
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the index array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapErrorBars(Graph *graphPtr, BarElement *elemPtr, BarStyle **dataToStyle)
+{
+ int n, nPoints;
+ Region2d reg;
+
+ Blt_GraphExtents(graphPtr, ®);
+ nPoints = NUMBEROFPOINTS(elemPtr);
+ if (elemPtr->xError.nValues > 0) {
+ n = MIN(elemPtr->xError.nValues, nPoints);
+ } else {
+ n = MIN3(elemPtr->xHigh.nValues, elemPtr->xLow.nValues, nPoints);
+ }
+ if (n > 0) {
+ Segment2d *bars;
+ Segment2d *segPtr;
+ int *map;
+ int *indexPtr;
+ int i;
+
+ segPtr = bars = malloc(n * 3 * sizeof(Segment2d));
+ indexPtr = map = malloc(n * 3 * sizeof(int));
+ for (i = 0; i < n; i++) {
+ double x, y;
+ double high, low;
+ BarStyle *stylePtr;
+
+ x = elemPtr->x.values[i];
+ y = elemPtr->y.values[i];
+ stylePtr = dataToStyle[i];
+ if ((isfinite(x)) && (isfinite(y))) {
+ if (elemPtr->xError.nValues > 0) {
+ high = x + elemPtr->xError.values[i];
+ low = x - elemPtr->xError.values[i];
+ } else {
+ high = elemPtr->xHigh.values[i];
+ low = elemPtr->xLow.values[i];
+ }
+ if ((isfinite(high)) && (isfinite(low))) {
+ Point2d p, q;
+
+ p = Blt_Map2D(graphPtr, high, y, &elemPtr->axes);
+ q = Blt_Map2D(graphPtr, low, y, &elemPtr->axes);
+ segPtr->p = p;
+ segPtr->q = q;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Left cap */
+ segPtr->p.x = segPtr->q.x = p.x;
+ segPtr->p.y = p.y - stylePtr->errorBarCapWidth;
+ segPtr->q.y = p.y + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Right cap */
+ segPtr->p.x = segPtr->q.x = q.x;
+ segPtr->p.y = q.y - stylePtr->errorBarCapWidth;
+ segPtr->q.y = q.y + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ }
+ }
+ }
+ elemPtr->xeb.segments = bars;
+ elemPtr->xeb.length = segPtr - bars;
+ elemPtr->xeb.map = map;
+ }
+ if (elemPtr->yError.nValues > 0) {
+ n = MIN(elemPtr->yError.nValues, nPoints);
+ } else {
+ n = MIN3(elemPtr->yHigh.nValues, elemPtr->yLow.nValues, nPoints);
+ }
+ if (n > 0) {
+ Segment2d *bars;
+ Segment2d *segPtr;
+ int *map;
+ int *indexPtr;
+ int i;
+
+ segPtr = bars = malloc(n * 3 * sizeof(Segment2d));
+ indexPtr = map = malloc(n * 3 * sizeof(int));
+ for (i = 0; i < n; i++) {
+ double x, y;
+ double high, low;
+ BarStyle *stylePtr;
+
+ x = elemPtr->x.values[i];
+ y = elemPtr->y.values[i];
+ stylePtr = dataToStyle[i];
+ if ((isfinite(x)) && (isfinite(y))) {
+ if (elemPtr->yError.nValues > 0) {
+ high = y + elemPtr->yError.values[i];
+ low = y - elemPtr->yError.values[i];
+ } else {
+ high = elemPtr->yHigh.values[i];
+ low = elemPtr->yLow.values[i];
+ }
+ if ((isfinite(high)) && (isfinite(low))) {
+ Point2d p, q;
+
+ p = Blt_Map2D(graphPtr, x, high, &elemPtr->axes);
+ q = Blt_Map2D(graphPtr, x, low, &elemPtr->axes);
+ segPtr->p = p;
+ segPtr->q = q;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Top cap. */
+ segPtr->p.y = segPtr->q.y = p.y;
+ segPtr->p.x = p.x - stylePtr->errorBarCapWidth;
+ segPtr->q.x = p.x + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Bottom cap. */
+ segPtr->p.y = segPtr->q.y = q.y;
+ segPtr->p.x = q.x - stylePtr->errorBarCapWidth;
+ segPtr->q.x = q.x + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(®, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ }
+ }
+ }
+ elemPtr->yeb.segments = bars;
+ elemPtr->yeb.length = segPtr - bars;
+ elemPtr->yeb.map = map;
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapBarProc --
+ *
+ * Calculates the actual window coordinates of the bar element. The
+ * window coordinates are saved in the bar element structure.
+ *
+ * Results:
+ * None.
+ *
+ * Notes:
+ * A bar can have multiple segments (more than one x,y pairs). In this
+ * case, the bar can be represented as either a set of non-contiguous
+ * bars or a single multi-segmented (stacked) bar.
+ *
+ * The x-axis layout for a barchart may be presented in one of two ways.
+ * If abscissas are used, the bars are placed at those coordinates.
+ * Otherwise, the range will represent the number of values.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapBarProc(Graph *graphPtr, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ BarStyle **dataToStyle;
+ double *x, *y;
+ double barWidth, barOffset;
+ double baseline, ybot;
+ int *barToData; /* Maps bars to data point indices */
+ int invertBar;
+ int nPoints, count;
+ XRectangle *rp, *bars;
+ int i;
+ int size;
+
+ ResetBar(elemPtr);
+ nPoints = NUMBEROFPOINTS(elemPtr);
+ if (nPoints < 1) {
+ return; /* No data points */
+ }
+ barWidth = graphPtr->barWidth;
+ barWidth = (elemPtr->barWidth > 0.0f)
+ ? elemPtr->barWidth : graphPtr->barWidth;
+ baseline = (elemPtr->axes.y->logScale) ? 0.0 : graphPtr->baseline;
+ barOffset = barWidth * 0.5;
+
+ /*
+ * Create an array of bars representing the screen coordinates of all the
+ * segments in the bar.
+ */
+ bars = calloc(nPoints, sizeof(XRectangle));
+ barToData = calloc(nPoints, sizeof(int));
+
+ x = elemPtr->x.values, y = elemPtr->y.values;
+ count = 0;
+ for (rp = bars, i = 0; i < nPoints; i++) {
+ Point2d c1, c2; /* Two opposite corners of the rectangle
+ * in graph coordinates. */
+ double dx, dy;
+ int height;
+ double right, left, top, bottom;
+
+ if (((x[i] - barWidth) > elemPtr->axes.x->axisRange.max) ||
+ ((x[i] + barWidth) < elemPtr->axes.x->axisRange.min)) {
+ continue; /* Abscissa is out of range of the
+ * x-axis */
+ }
+ c1.x = x[i] - barOffset;
+ c1.y = y[i];
+ c2.x = c1.x + barWidth;
+ c2.y = baseline;
+
+ /*
+ * If the mode is "aligned" or "stacked" we need to adjust the x or y
+ * coordinates of the two corners.
+ */
+
+ if ((graphPtr->nBarGroups > 0) && (graphPtr->mode != BARS_INFRONT) &&
+ (!graphPtr->stackAxes)) {
+ Blt_HashEntry *hPtr;
+ BarSetKey key;
+
+ key.value = (float)x[i];
+ key.axes = elemPtr->axes;
+ key.axes.y = NULL;
+ hPtr = Blt_FindHashEntry(&graphPtr->setTable, (char *)&key);
+ if (hPtr != NULL) {
+ Blt_HashTable *tablePtr;
+ const char *name;
+
+ tablePtr = Blt_GetHashValue(hPtr);
+ name = (elemPtr->groupName != NULL) ? elemPtr->groupName :
+ elemPtr->axes.y->obj.name;
+ hPtr = Blt_FindHashEntry(tablePtr, name);
+ if (hPtr != NULL) {
+ BarGroup *groupPtr;
+ double slice, width, offset;
+
+ groupPtr = Blt_GetHashValue(hPtr);
+ slice = barWidth / (double)graphPtr->maxBarSetSize;
+ offset = (slice * groupPtr->index);
+ if (graphPtr->maxBarSetSize > 1) {
+ offset += slice * 0.05;
+ slice *= 0.90;
+ }
+ switch (graphPtr->mode) {
+ case BARS_STACKED:
+ groupPtr->count++;
+ c2.y = groupPtr->lastY;
+ c1.y += c2.y;
+ groupPtr->lastY = c1.y;
+ c1.x += offset;
+ c2.x = c1.x + slice;
+ break;
+
+ case BARS_ALIGNED:
+ slice /= groupPtr->nSegments;
+ c1.x += offset + (slice * groupPtr->count);
+ c2.x = c1.x + slice;
+ groupPtr->count++;
+ break;
+
+ case BARS_OVERLAP:
+ slice /= (groupPtr->nSegments + 1);
+ width = slice + slice;
+ groupPtr->count++;
+ c1.x += offset +
+ (slice * (groupPtr->nSegments - groupPtr->count));
+ c2.x = c1.x + width;
+ break;
+
+ case BARS_INFRONT:
+ break;
+ }
+ }
+ }
+ }
+ invertBar = FALSE;
+ if (c1.y < c2.y) {
+ double temp;
+
+ /* Handle negative bar values by swapping ordinates */
+ temp = c1.y, c1.y = c2.y, c2.y = temp;
+ invertBar = TRUE;
+ }
+ /*
+ * Get the two corners of the bar segment and compute the rectangle
+ */
+ ybot = c2.y;
+ c1 = Blt_Map2D(graphPtr, c1.x, c1.y, &elemPtr->axes);
+ c2 = Blt_Map2D(graphPtr, c2.x, c2.y, &elemPtr->axes);
+ if ((ybot == 0.0) && (elemPtr->axes.y->logScale)) {
+ c2.y = graphPtr->bottom;
+ }
+
+ if (c2.y < c1.y) {
+ double t;
+ t = c1.y, c1.y = c2.y, c2.y = t;
+ }
+ if (c2.x < c1.x) {
+ double t;
+ t = c1.x, c1.x = c2.x, c2.x = t;
+ }
+ if ((c1.x > graphPtr->right) || (c2.x < graphPtr->left) ||
+ (c1.y > graphPtr->bottom) || (c2.y < graphPtr->top)) {
+ continue;
+ }
+ /* Bound the bars horizontally by the width of the graph window */
+ /* Bound the bars vertically by the position of the axis. */
+ if (graphPtr->stackAxes) {
+ top = elemPtr->axes.y->screenMin;
+ bottom = elemPtr->axes.y->screenMin + elemPtr->axes.y->screenRange;
+ left = graphPtr->left;
+ right = graphPtr->right;
+ } else {
+ left = top = 0;
+ bottom = right = 10000;
+ /* Shouldn't really have a call to Tk_Width or Tk_Height in
+ * mapping routine. We only want to clamp the bar segment to the
+ * size of the window if we're actually mapped onscreen. */
+ if (Tk_Height(graphPtr->tkwin) > 1) {
+ bottom = Tk_Height(graphPtr->tkwin);
+ }
+ if (Tk_Width(graphPtr->tkwin) > 1) {
+ right = Tk_Width(graphPtr->tkwin);
+ }
+ }
+ CLAMP(c1.y, top, bottom);
+ CLAMP(c2.y, top, bottom);
+ CLAMP(c1.x, left, right);
+ CLAMP(c2.x, left, right);
+ dx = fabs(c1.x - c2.x);
+ dy = fabs(c1.y - c2.y);
+ if ((dx == 0) || (dy == 0)) {
+ continue;
+ }
+ height = (int)dy;
+ if (invertBar) {
+ rp->y = (short int)MIN(c1.y, c2.y);
+ } else {
+ rp->y = (short int)(MAX(c1.y, c2.y)) - height;
+ }
+ rp->x = (short int)MIN(c1.x, c2.x);
+ rp->width = (short int)dx + 1;
+ rp->width |= 0x1;
+ if (rp->width < 1) {
+ rp->width = 1;
+ }
+ rp->height = height + 1;
+ if (rp->height < 1) {
+ rp->height = 1;
+ }
+ barToData[count] = i; /* Save the data index corresponding to
+ * the rectangle */
+ count++;
+ rp++;
+ }
+ elemPtr->nBars = count;
+ elemPtr->bars = bars;
+ elemPtr->barToData = barToData;
+ if (elemPtr->nActiveIndices > 0) {
+ MapActiveBars(elemPtr);
+ }
+
+ size = 20;
+ if (count > 0) {
+ size = bars->width;
+ }
+ {
+ Blt_ChainLink link;
+
+ /* Set the symbol size of all the pen styles. */
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->symbolSize = size;
+ stylePtr->errorBarCapWidth =
+ (stylePtr->penPtr->errorBarCapWidth > 0)
+ ? stylePtr->penPtr->errorBarCapWidth : (size * 66666) / 100000;
+ stylePtr->errorBarCapWidth /= 2;
+ }
+ }
+ dataToStyle = (BarStyle **)Blt_StyleMap((Element *)elemPtr);
+ if (((elemPtr->yHigh.nValues > 0) && (elemPtr->yLow.nValues > 0)) ||
+ ((elemPtr->xHigh.nValues > 0) && (elemPtr->xLow.nValues > 0)) ||
+ (elemPtr->xError.nValues > 0) || (elemPtr->yError.nValues > 0)) {
+ MapErrorBars(graphPtr, elemPtr, dataToStyle);
+ }
+ MergePens(elemPtr, dataToStyle);
+ free(dataToStyle);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawSymbolProc --
+ *
+ * Draw a symbol centered at the given x,y window coordinate based upon
+ * the element symbol type and size.
+ *
+ * Results:
+ * None.
+ *
+ * Problems:
+ * Most notable is the round-off errors generated when calculating the
+ * centered position of the symbol.
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+DrawSymbolProc(Graph *graphPtr, Drawable drawable, Element *basePtr,
+ int x, int y, int size)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ BarPen *penPtr;
+ int radius;
+
+ penPtr = NORMALPEN(elemPtr);
+ if ((penPtr->fill == NULL) && (penPtr->outlineColor == NULL)) {
+ return;
+ }
+ radius = (size / 2);
+ size--;
+
+ x -= radius;
+ y -= radius;
+ if (penPtr->fillGC != NULL) {
+ XSetTSOrigin(graphPtr->display, penPtr->fillGC, x, y);
+ }
+ if (penPtr->stipple != None) {
+ XFillRectangle(graphPtr->display, drawable, penPtr->fillGC, x, y,
+ size, size);
+ } else {
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, penPtr->fill,
+ x, y, size, size, penPtr->borderWidth, penPtr->relief);
+ }
+ XDrawRectangle(graphPtr->display, drawable, penPtr->outlineGC, x, y,
+ size, size);
+ if (penPtr->fillGC != NULL) {
+ XSetTSOrigin(graphPtr->display, penPtr->fillGC, 0, 0);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawBarSegments --
+ *
+ * Draws each of the rectangular segments for the element.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawBarSegments(Graph *graphPtr, Drawable drawable, BarPen *penPtr,
+ XRectangle *bars, int nBars)
+{
+ TkRegion rgn;
+
+ {
+ XRectangle clip;
+ clip.x = graphPtr->left;
+ clip.y = graphPtr->top;
+ clip.width = graphPtr->right - graphPtr->left + 1;
+ clip.height = graphPtr->bottom - graphPtr->top + 1;
+ rgn = TkCreateRegion();
+ TkUnionRectWithRegion(&clip, rgn, rgn);
+ }
+ if (penPtr->fill != NULL) {
+ XRectangle *rp, *rend;
+ int hasOutline;
+ int relief;
+
+ relief = (penPtr->relief == TK_RELIEF_SOLID)
+ ? TK_RELIEF_FLAT: penPtr->relief;
+ hasOutline = ((relief == TK_RELIEF_FLAT) &&
+ (penPtr->outlineColor != NULL));
+ if (penPtr->stipple != None) {
+ TkSetRegion(graphPtr->display, penPtr->fillGC, rgn);
+ }
+ Blt_SetBackgroundClipRegion(graphPtr->tkwin, penPtr->fill, rgn);
+ if (hasOutline) {
+ TkSetRegion(graphPtr->display, penPtr->outlineGC, rgn);
+ }
+ for (rp = bars, rend = rp + nBars; rp < rend; rp++) {
+ if (penPtr->stipple != None) {
+ XFillRectangle(graphPtr->display, drawable, penPtr->fillGC,
+ rp->x, rp->y, rp->width, rp->height);
+ } else {
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable,
+ penPtr->fill, rp->x, rp->y, rp->width, rp->height,
+ penPtr->borderWidth, relief);
+ }
+ if (hasOutline) {
+ XDrawRectangle(graphPtr->display, drawable, penPtr->outlineGC,
+ rp->x, rp->y, rp->width, rp->height);
+ }
+ }
+ Blt_UnsetBackgroundClipRegion(graphPtr->tkwin, penPtr->fill);
+ if (hasOutline) {
+ XSetClipMask(graphPtr->display, penPtr->outlineGC, None);
+ }
+ if (penPtr->stipple != None) {
+ XSetClipMask(graphPtr->display, penPtr->fillGC, None);
+ }
+ } else if (penPtr->outlineColor != NULL) {
+ TkSetRegion(graphPtr->display, penPtr->outlineGC, rgn);
+ XDrawRectangles(graphPtr->display, drawable, penPtr->outlineGC, bars,
+ nBars);
+ XSetClipMask(graphPtr->display, penPtr->outlineGC, None);
+ }
+ TkDestroyRegion(rgn);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawBarValues --
+ *
+ * Draws the numeric value of the bar.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawBarValues(Graph *graphPtr, Drawable drawable, BarElement *elemPtr,
+ BarPen *penPtr, XRectangle *bars, int nBars, int *barToData)
+{
+ XRectangle *rp, *rend;
+ int count;
+ const char *fmt;
+
+ fmt = penPtr->valueFormat;
+ if (fmt == NULL) {
+ fmt = "%g";
+ }
+ count = 0;
+ for (rp = bars, rend = rp + nBars; rp < rend; rp++) {
+ Point2d anchorPos;
+ double x, y;
+ char string[TCL_DOUBLE_SPACE * 2 + 2];
+
+ x = elemPtr->x.values[barToData[count]];
+ y = elemPtr->y.values[barToData[count]];
+
+ count++;
+ if (penPtr->valueShow == SHOW_X) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ } else if (penPtr->valueShow == SHOW_Y) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, y);
+ } else if (penPtr->valueShow == SHOW_BOTH) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ strcat(string, ",");
+ sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y);
+ }
+ if (graphPtr->inverted) {
+ anchorPos.y = rp->y + rp->height * 0.5;
+ anchorPos.x = rp->x + rp->width;
+ if (x < graphPtr->baseline) {
+ anchorPos.x -= rp->width;
+ }
+ } else {
+ anchorPos.x = rp->x + rp->width * 0.5;
+ anchorPos.y = rp->y;
+ if (y < graphPtr->baseline) {
+ anchorPos.y += rp->height;
+ }
+ }
+ Blt_DrawText(graphPtr->tkwin, drawable, string, &penPtr->valueStyle,
+ (int)anchorPos.x, (int)anchorPos.y);
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawNormalBar --
+ *
+ * Draws the rectangle representing the bar element. If the relief
+ * option is set to "raised" or "sunken" and the bar borderwidth is set
+ * (borderwidth > 0), a 3D border is drawn around the bar.
+ *
+ * Don't draw bars that aren't visible (i.e. within the limits of the
+ * axis).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * X drawing commands are output.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawNormalBarProc(Graph *graphPtr, Drawable drawable, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ int count;
+ Blt_ChainLink link;
+
+ count = 0;
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+ BarPen *penPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = stylePtr->penPtr;
+ if (stylePtr->nBars > 0) {
+ DrawBarSegments(graphPtr, drawable, penPtr, stylePtr->bars,
+ stylePtr->nBars);
+ }
+ if ((stylePtr->xeb.length > 0) && (penPtr->errorBarShow & SHOW_X)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
+ stylePtr->xeb.segments, stylePtr->xeb.length);
+ }
+ if ((stylePtr->yeb.length > 0) && (penPtr->errorBarShow & SHOW_Y)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
+ stylePtr->yeb.segments, stylePtr->yeb.length);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawBarValues(graphPtr, drawable, elemPtr, penPtr,
+ stylePtr->bars, stylePtr->nBars,
+ elemPtr->barToData + count);
+ }
+ count += stylePtr->nBars;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawActiveBar --
+ *
+ * Draws bars representing the active segments of the bar element. If
+ * the -relief option is set (other than "flat") and the borderwidth is
+ * greater than 0, a 3D border is drawn around the each bar segment.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * X drawing commands are output.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawActiveBarProc(Graph *graphPtr, Drawable drawable, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+
+ if (elemPtr->activePenPtr != NULL) {
+ BarPen *penPtr = elemPtr->activePenPtr;
+
+ if (elemPtr->nActiveIndices > 0) {
+ if (elemPtr->flags & ACTIVE_PENDING) {
+ MapActiveBars(elemPtr);
+ }
+ DrawBarSegments(graphPtr, drawable, penPtr, elemPtr->activeRects,
+ elemPtr->nActive);
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawBarValues(graphPtr, drawable, elemPtr, penPtr,
+ elemPtr->activeRects, elemPtr->nActive,
+ elemPtr->activeToData);
+ }
+ } else if (elemPtr->nActiveIndices < 0) {
+ DrawBarSegments(graphPtr, drawable, penPtr, elemPtr->bars,
+ elemPtr->nBars);
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawBarValues(graphPtr, drawable, elemPtr, penPtr,
+ elemPtr->bars, elemPtr->nBars, elemPtr->barToData);
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SymbolToPostScript --
+ *
+ * Draw a symbol centered at the given x,y window coordinate based upon
+ * the element symbol type and size.
+ *
+ * Results:
+ * None.
+ *
+ * Problems:
+ * Most notable is the round-off errors generated when calculating the
+ * centered position of the symbol.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+SymbolToPostScriptProc(
+ Graph *graphPtr,
+ Blt_Ps ps,
+ Element *basePtr,
+ double x, double y,
+ int size)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ BarPen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ if ((penPtr->fill == NULL) && (penPtr->outlineColor == NULL)) {
+ return;
+ }
+ /*
+ * Build a PostScript procedure to draw the fill and outline of the symbol
+ * after the path of the symbol shape has been formed
+ */
+ Blt_Ps_Append(ps, "\n"
+ "/DrawSymbolProc {\n"
+ "gsave\n ");
+ if (penPtr->stipple != None) {
+ if (penPtr->fill != NULL) {
+ Blt_Ps_XSetBackground(ps, Blt_BackgroundBorderColor(penPtr->fill));
+ Blt_Ps_Append(ps, " gsave fill grestore\n ");
+ }
+ if (penPtr->outlineColor != NULL) {
+ Blt_Ps_XSetForeground(ps, penPtr->outlineColor);
+ } else {
+ Blt_Ps_XSetForeground(ps, Blt_BackgroundBorderColor(penPtr->fill));
+ }
+ Blt_Ps_XSetStipple(ps, graphPtr->display, penPtr->stipple);
+ } else if (penPtr->outlineColor != NULL) {
+ Blt_Ps_XSetForeground(ps, penPtr->outlineColor);
+ Blt_Ps_Append(ps, " fill\n");
+ }
+ Blt_Ps_Append(ps, " grestore\n");
+ Blt_Ps_Append(ps, "} def\n\n");
+ Blt_Ps_Format(ps, "%g %g %d Sq\n", x, y, size);
+}
+
+static void
+SegmentsToPostScript(Graph *graphPtr, Blt_Ps ps, BarPen *penPtr,
+ XRectangle *bars, int nBars)
+{
+ XRectangle *rp, *rend;
+
+ if ((penPtr->fill == NULL) && (penPtr->outlineColor == NULL)) {
+ return;
+ }
+ for (rp = bars, rend = rp + nBars; rp < rend; rp++) {
+ if ((rp->width < 1) || (rp->height < 1)) {
+ continue;
+ }
+ if (penPtr->stipple != None) {
+ Blt_Ps_Rectangle(ps, rp->x, rp->y, rp->width - 1, rp->height - 1);
+ if (penPtr->fill != NULL) {
+ Blt_Ps_XSetBackground(ps,Blt_BackgroundBorderColor(penPtr->fill));
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ }
+ if (penPtr->outlineColor != NULL) {
+ Blt_Ps_XSetForeground(ps, penPtr->outlineColor);
+ } else {
+ Blt_Ps_XSetForeground(ps,Blt_BackgroundBorderColor(penPtr->fill));
+ }
+ Blt_Ps_XSetStipple(ps, graphPtr->display, penPtr->stipple);
+ } else if (penPtr->outlineColor != NULL) {
+ Blt_Ps_XSetForeground(ps, penPtr->outlineColor);
+ Blt_Ps_XFillRectangle(ps, (double)rp->x, (double)rp->y,
+ (int)rp->width - 1, (int)rp->height - 1);
+ }
+ if ((penPtr->fill != NULL) && (penPtr->borderWidth > 0) &&
+ (penPtr->relief != TK_RELIEF_FLAT)) {
+ Blt_Ps_Draw3DRectangle(ps, Blt_BackgroundBorder(penPtr->fill),
+ (double)rp->x, (double)rp->y, (int)rp->width, (int)rp->height,
+ penPtr->borderWidth, penPtr->relief);
+ }
+ }
+}
+
+static void
+BarValuesToPostScript(Graph *graphPtr, Blt_Ps ps, BarElement *elemPtr,
+ BarPen *penPtr, XRectangle *bars, int nBars,
+ int *barToData)
+{
+ XRectangle *rp, *rend;
+ int count;
+ const char *fmt;
+ char string[TCL_DOUBLE_SPACE * 2 + 2];
+ double x, y;
+ Point2d anchorPos;
+
+ count = 0;
+ fmt = penPtr->valueFormat;
+ if (fmt == NULL) {
+ fmt = "%g";
+ }
+ for (rp = bars, rend = rp + nBars; rp < rend; rp++) {
+ x = elemPtr->x.values[barToData[count]];
+ y = elemPtr->y.values[barToData[count]];
+ count++;
+ if (penPtr->valueShow == SHOW_X) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ } else if (penPtr->valueShow == SHOW_Y) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, y);
+ } else if (penPtr->valueShow == SHOW_BOTH) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ strcat(string, ",");
+ sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y);
+ }
+ if (graphPtr->inverted) {
+ anchorPos.y = rp->y + rp->height * 0.5;
+ anchorPos.x = rp->x + rp->width;
+ if (x < graphPtr->baseline) {
+ anchorPos.x -= rp->width;
+ }
+ } else {
+ anchorPos.x = rp->x + rp->width * 0.5;
+ anchorPos.y = rp->y;
+ if (y < graphPtr->baseline) {
+ anchorPos.y += rp->height;
+ }
+ }
+ Blt_Ps_DrawText(ps, string, &penPtr->valueStyle, anchorPos.x,
+ anchorPos.y);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ActiveBarToPostScript --
+ *
+ * Similar to the NormalBarToPostScript procedure, generates PostScript
+ * commands to display the bars representing the active bar segments of
+ * the element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript pen width, dashes, and color settings are changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+ActiveBarToPostScriptProc(Graph *graphPtr, Blt_Ps ps, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+
+ if (elemPtr->activePenPtr != NULL) {
+ BarPen *penPtr = elemPtr->activePenPtr;
+
+ if (elemPtr->nActiveIndices > 0) {
+ if (elemPtr->flags & ACTIVE_PENDING) {
+ MapActiveBars(elemPtr);
+ }
+ SegmentsToPostScript(graphPtr, ps, penPtr, elemPtr->activeRects,
+ elemPtr->nActive);
+ if (penPtr->valueShow != SHOW_NONE) {
+ BarValuesToPostScript(graphPtr, ps, elemPtr, penPtr,
+ elemPtr->activeRects, elemPtr->nActive, elemPtr->activeToData);
+ }
+ } else if (elemPtr->nActiveIndices < 0) {
+ SegmentsToPostScript(graphPtr, ps, penPtr, elemPtr->bars,
+ elemPtr->nBars);
+ if (penPtr->valueShow != SHOW_NONE) {
+ BarValuesToPostScript(graphPtr, ps, elemPtr, penPtr,
+ elemPtr->bars, elemPtr->nBars, elemPtr->barToData);
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NormalBarToPostScript --
+ *
+ * Generates PostScript commands to form the bars representing the
+ * segments of the bar element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript pen width, dashes, and color settings are changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+NormalBarToPostScriptProc(Graph *graphPtr, Blt_Ps ps, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+ Blt_ChainLink link;
+ int count;
+
+ count = 0;
+ for (link = Blt_Chain_FirstLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ BarStyle *stylePtr;
+ BarPen *penPtr;
+ XColor *colorPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = stylePtr->penPtr;
+ if (stylePtr->nBars > 0) {
+ SegmentsToPostScript(graphPtr, ps, penPtr, stylePtr->bars,
+ stylePtr->nBars);
+ }
+ colorPtr = penPtr->errorBarColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = penPtr->outlineColor;
+ }
+ if ((stylePtr->xeb.length > 0) && (penPtr->errorBarShow & SHOW_X)) {
+ Blt_Ps_XSetLineAttributes(ps, colorPtr, penPtr->errorBarLineWidth,
+ NULL, CapButt, JoinMiter);
+ Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments,
+ stylePtr->xeb.length);
+ }
+ if ((stylePtr->yeb.length > 0) && (penPtr->errorBarShow & SHOW_Y)) {
+ Blt_Ps_XSetLineAttributes(ps, colorPtr, penPtr->errorBarLineWidth,
+ NULL, CapButt, JoinMiter);
+ Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments,
+ stylePtr->yeb.length);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ BarValuesToPostScript(graphPtr, ps, elemPtr, penPtr,
+ stylePtr->bars, stylePtr->nBars, elemPtr->barToData + count);
+ }
+ count += stylePtr->nBars;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyBar --
+ *
+ * Release memory and resources allocated for the bar element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the bar element is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DestroyBarProc(Graph *graphPtr, Element *basePtr)
+{
+ BarElement *elemPtr = (BarElement *)basePtr;
+
+ DestroyBarPen(graphPtr, elemPtr->builtinPenPtr);
+ if (elemPtr->activePenPtr != NULL) {
+ Blt_FreePen((Pen *)elemPtr->activePenPtr);
+ }
+ ResetBar(elemPtr);
+ if (elemPtr->stylePalette != NULL) {
+ Blt_FreeStylePalette(elemPtr->stylePalette);
+ Blt_Chain_Destroy(elemPtr->stylePalette);
+ }
+ if (elemPtr->activeIndices != NULL) {
+ free(elemPtr->activeIndices);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_BarElement --
+ *
+ * Allocate memory and initialize methods for the new bar element.
+ *
+ * Results:
+ * The pointer to the newly allocated element structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the bar element structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static ElementProcs barProcs = {
+ ClosestBarProc,
+ ConfigureBarProc,
+ DestroyBarProc,
+ DrawActiveBarProc,
+ DrawNormalBarProc,
+ DrawSymbolProc,
+ GetBarExtentsProc,
+ ActiveBarToPostScriptProc,
+ NormalBarToPostScriptProc,
+ SymbolToPostScriptProc,
+ MapBarProc,
+};
+
+
+Element *
+Blt_BarElement(Graph *graphPtr, const char *name, ClassId classId)
+{
+ BarElement *elemPtr;
+
+ elemPtr = calloc(1, sizeof(BarElement));
+ elemPtr->procsPtr = &barProcs;
+ elemPtr->configSpecs = barElemConfigSpecs;
+ elemPtr->legendRelief = TK_RELIEF_FLAT;
+ Blt_GraphSetObjectClass(&elemPtr->obj, classId);
+ elemPtr->obj.name = Blt_Strdup(name);
+ elemPtr->obj.graphPtr = graphPtr;
+ /* By default, an element's name and label are the same. */
+ elemPtr->label = Blt_Strdup(name);
+ elemPtr->builtinPenPtr = &elemPtr->builtinPen;
+ InitializeBarPen(elemPtr->builtinPenPtr);
+ elemPtr->stylePalette = Blt_Chain_Create();
+ bltBarStylesOption.clientData = (ClientData)sizeof(BarStyle);
+ return (Element *)elemPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitBarSetTable --
+ *
+ * Generate a table of abscissa frequencies. Duplicate x-coordinates
+ * (depending upon the bar drawing mode) indicate that something special
+ * should be done with each bar segment mapped to the same abscissa
+ * (i.e. it should be stacked, aligned, or overlay-ed with other segments)
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is allocated for the bar element structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_InitBarSetTable(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+ int nStacks, nSegs;
+ Blt_HashTable setTable;
+ int sum, max;
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ /*
+ * Free resources associated with a previous frequency table. This includes
+ * the array of frequency information and the table itself
+ */
+ Blt_DestroyBarSets(graphPtr);
+ if (graphPtr->mode == BARS_INFRONT) {
+ return; /* No set table is needed for
+ * "infront" mode */
+ }
+ Blt_InitHashTable(&graphPtr->setTable, sizeof(BarSetKey) / sizeof(int));
+
+ /*
+ * Initialize a hash table and fill it with unique abscissas. Keep track
+ * of the frequency of each x-coordinate and how many abscissas have
+ * duplicate mappings.
+ */
+ Blt_InitHashTable(&setTable, sizeof(BarSetKey) / sizeof(int));
+ nSegs = nStacks = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ BarElement *elemPtr;
+ double *x, *xend;
+ int nPoints;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((elemPtr->flags & HIDE) || (elemPtr->obj.classId != CID_ELEM_BAR)) {
+ continue;
+ }
+ nSegs++;
+ nPoints = NUMBEROFPOINTS(elemPtr);
+ for (x = elemPtr->x.values, xend = x + nPoints; x < xend; x++) {
+ Blt_HashEntry *hPtr;
+ Blt_HashTable *tablePtr;
+ BarSetKey key;
+ int isNew;
+ size_t count;
+ const char *name;
+
+ key.value = *x;
+ key.axes = elemPtr->axes;
+ key.axes.y = NULL;
+ hPtr = Blt_CreateHashEntry(&setTable, (char *)&key, &isNew);
+ if (isNew) {
+ tablePtr = malloc(sizeof(Blt_HashTable));
+ Blt_InitHashTable(tablePtr, BLT_STRING_KEYS);
+ Blt_SetHashValue(hPtr, tablePtr);
+ } else {
+ tablePtr = Blt_GetHashValue(hPtr);
+ }
+ name = (elemPtr->groupName != NULL) ? elemPtr->groupName :
+ elemPtr->axes.y->obj.name;
+ hPtr = Blt_CreateHashEntry(tablePtr, name, &isNew);
+ if (isNew) {
+ count = 1;
+ } else {
+ count = (size_t)Blt_GetHashValue(hPtr);
+ count++;
+ }
+ Blt_SetHashValue(hPtr, (ClientData)count);
+ }
+ }
+ if (setTable.numEntries == 0) {
+ return; /* No bar elements to be displayed */
+ }
+ sum = max = 0;
+ for (hPtr = Blt_FirstHashEntry(&setTable, &iter); hPtr != NULL;
+ hPtr = Blt_NextHashEntry(&iter)) {
+ Blt_HashTable *tablePtr;
+ Blt_HashEntry *hPtr2;
+ BarSetKey *keyPtr;
+ int isNew;
+
+ keyPtr = (BarSetKey *)Blt_GetHashKey(&setTable, hPtr);
+ hPtr2 = Blt_CreateHashEntry(&graphPtr->setTable, (char *)keyPtr,&isNew);
+ tablePtr = Blt_GetHashValue(hPtr);
+ Blt_SetHashValue(hPtr2, tablePtr);
+ if (max < tablePtr->numEntries) {
+ max = tablePtr->numEntries; /* # of stacks in group. */
+ }
+ sum += tablePtr->numEntries;
+ }
+ Blt_DeleteHashTable(&setTable);
+ if (sum > 0) {
+ BarGroup *groupPtr;
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ graphPtr->barGroups = calloc(sum, sizeof(BarGroup));
+ groupPtr = graphPtr->barGroups;
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->setTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ BarSetKey *keyPtr;
+ Blt_HashTable *tablePtr;
+ Blt_HashEntry *hPtr2;
+ Blt_HashSearch iter2;
+ size_t xcount;
+
+ tablePtr = Blt_GetHashValue(hPtr);
+ keyPtr = (BarSetKey *)Blt_GetHashKey(&setTable, hPtr);
+ xcount = 0;
+ for (hPtr2 = Blt_FirstHashEntry(tablePtr, &iter2); hPtr2!=NULL;
+ hPtr2 = Blt_NextHashEntry(&iter2)) {
+ size_t count;
+
+ count = (size_t)Blt_GetHashValue(hPtr2);
+ groupPtr->nSegments = count;
+ groupPtr->axes = keyPtr->axes;
+ Blt_SetHashValue(hPtr2, groupPtr);
+ groupPtr->index = xcount++;
+ groupPtr++;
+ }
+ }
+ }
+ graphPtr->maxBarSetSize = max;
+ graphPtr->nBarGroups = sum;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ComputeStacks --
+ *
+ * Determine the height of each stack of bar segments. A stack is created
+ * by designating two or more points with the same abscissa. Each ordinate
+ * defines the height of a segment in the stack. This procedure simply
+ * looks at all the data points summing the heights of each stacked
+ * segment. The sum is saved in the frequency information table. This
+ * value will be used to calculate the y-axis limits (data limits aren't
+ * sufficient).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The heights of each stack is computed. CheckBarGroups will use this
+ * information to adjust the y-axis limits if necessary.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ComputeBarStacks(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ if ((graphPtr->mode != BARS_STACKED) || (graphPtr->nBarGroups == 0)) {
+ return;
+ }
+
+ /* Initialize the stack sums to zero. */
+ {
+ BarGroup *gp, *gend;
+
+ for (gp = graphPtr->barGroups, gend = gp + graphPtr->nBarGroups;
+ gp < gend; gp++) {
+ gp->sum = 0.0;
+ }
+ }
+
+ /* Consider each bar x-y coordinate. Add the ordinates of duplicate
+ * abscissas. */
+
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ BarElement *elemPtr;
+ double *x, *y, *xend;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((elemPtr->flags & HIDE) || (elemPtr->obj.classId != CID_ELEM_BAR)) {
+ continue;
+ }
+ for (x = elemPtr->x.values, y = elemPtr->y.values,
+ xend = x + NUMBEROFPOINTS(elemPtr); x < xend; x++, y++) {
+ BarSetKey key;
+ BarGroup *groupPtr;
+ Blt_HashEntry *hPtr;
+ Blt_HashTable *tablePtr;
+ const char *name;
+
+ key.value = *x;
+ key.axes = elemPtr->axes;
+ key.axes.y = NULL;
+ hPtr = Blt_FindHashEntry(&graphPtr->setTable, (char *)&key);
+ if (hPtr == NULL) {
+ continue;
+ }
+ tablePtr = Blt_GetHashValue(hPtr);
+ name = (elemPtr->groupName != NULL) ? elemPtr->groupName :
+ elemPtr->axes.y->obj.name;
+ hPtr = Blt_FindHashEntry(tablePtr, name);
+ if (hPtr == NULL) {
+ continue;
+ }
+ groupPtr = Blt_GetHashValue(hPtr);
+ groupPtr->sum += *y;
+ }
+ }
+}
+
+void
+Blt_ResetBarGroups(Graph *graphPtr)
+{
+ BarGroup *gp, *gend;
+
+ for (gp = graphPtr->barGroups, gend = gp + graphPtr->nBarGroups; gp < gend;
+ gp++) {
+ gp->lastY = 0.0;
+ gp->count = 0;
+ }
+}
+
+void
+Blt_DestroyBarSets(Graph *graphPtr)
+{
+ Blt_HashSearch iter;
+ Blt_HashEntry *hPtr;
+
+ if (graphPtr->barGroups != NULL) {
+ free(graphPtr->barGroups);
+ graphPtr->barGroups = NULL;
+ }
+ graphPtr->nBarGroups = 0;
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->setTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Blt_HashTable *tablePtr;
+
+ tablePtr = Blt_GetHashValue(hPtr);
+ Blt_DeleteHashTable(tablePtr);
+ free(tablePtr);
+ }
+ Blt_DeleteHashTable(&graphPtr->setTable);
+ Blt_InitHashTable(&graphPtr->setTable, sizeof(BarSetKey) / sizeof(int));
+}
diff --git a/tlt3.0/bltGrElem.c b/tlt3.0/bltGrElem.c
new file mode 100644
index 0000000..9abdc6e
--- /dev/null
+++ b/tlt3.0/bltGrElem.c
@@ -0,0 +1,2214 @@
+
+/*
+ * bltGrElem.c --
+ *
+ * This module implements generic elements for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+
+#define GRAPH_KEY "BLT Graph Data"
+
+/* Ignore elements that aren't in the display list or have been deleted. */
+#define IGNORE_ELEMENT(e) (((e)->link == NULL) || ((e)->flags & DELETE_PENDING))
+
+static Blt_OptionParseProc ObjToAlong;
+static Blt_OptionPrintProc AlongToObj;
+static Blt_CustomOption alongOption =
+{
+ ObjToAlong, AlongToObj, NULL, (ClientData)0
+};
+static Blt_OptionFreeProc FreeValues;
+static Blt_OptionParseProc ObjToValues;
+static Blt_OptionPrintProc ValuesToObj;
+Blt_CustomOption bltValuesOption =
+{
+ ObjToValues, ValuesToObj, FreeValues, (ClientData)0
+};
+static Blt_OptionFreeProc FreeValuePairs;
+static Blt_OptionParseProc ObjToValuePairs;
+static Blt_OptionPrintProc ValuePairsToObj;
+Blt_CustomOption bltValuePairsOption =
+{
+ ObjToValuePairs, ValuePairsToObj, FreeValuePairs, (ClientData)0
+};
+
+static Blt_OptionFreeProc FreeStyles;
+static Blt_OptionParseProc ObjToStyles;
+static Blt_OptionPrintProc StylesToObj;
+Blt_CustomOption bltLineStylesOption =
+{
+ ObjToStyles, StylesToObj, FreeStyles, (ClientData)0,
+};
+
+Blt_CustomOption bltBarStylesOption =
+{
+ ObjToStyles, StylesToObj, FreeStyles, (ClientData)0,
+};
+
+#include "bltGrElem.h"
+
+static Blt_VectorChangedProc VectorChangedProc;
+
+static void FindRange(ElemValues *valuesPtr);
+static void FreeDataValues(ElemValues *valuesPtr);
+static Tcl_FreeProc FreeElement;
+
+typedef int (GraphElementProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+/*
+ *---------------------------------------------------------------------------
+ * Custom option parse and print procedures
+ *---------------------------------------------------------------------------
+ */
+static int
+GetPenStyleFromObj(
+ Tcl_Interp *interp,
+ Graph *graphPtr,
+ Tcl_Obj *objPtr,
+ ClassId classId,
+ PenStyle *stylePtr)
+{
+ Pen *penPtr;
+ Tcl_Obj **objv;
+ int objc;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc != 1) && (objc != 3)) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "bad style entry \"",
+ Tcl_GetString(objPtr),
+ "\": should be \"penName\" or \"penName min max\"",
+ (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ if (Blt_GetPenFromObj(interp, graphPtr, objv[0], classId, &penPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 3) {
+ double min, max;
+
+ if ((Tcl_GetDoubleFromObj(interp, objv[1], &min) != TCL_OK) ||
+ (Tcl_GetDoubleFromObj(interp, objv[2], &max) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ SetWeight(stylePtr->weight, min, max);
+ }
+ stylePtr->penPtr = penPtr;
+ return TCL_OK;
+}
+
+static void
+FreeVectorSource(ElemValues *valuesPtr)
+{
+ if (valuesPtr->vectorSource.vector != NULL) {
+ Blt_SetVectorChangedProc(valuesPtr->vectorSource.vector, NULL, NULL);
+ Blt_FreeVectorId(valuesPtr->vectorSource.vector);
+ valuesPtr->vectorSource.vector = NULL;
+ }
+}
+
+static int
+FetchVectorValues(Tcl_Interp *interp, ElemValues *valuesPtr, Blt_Vector *vector)
+{
+ double *array;
+
+ if (valuesPtr->values == NULL) {
+ array = malloc(Blt_VecLength(vector) * sizeof(double));
+ } else {
+ array = realloc(valuesPtr->values,
+ Blt_VecLength(vector) * sizeof(double));
+ }
+ if (array == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't allocate new vector", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ memcpy(array, Blt_VecData(vector), sizeof(double) * Blt_VecLength(vector));
+ valuesPtr->min = Blt_VecMin(vector);
+ valuesPtr->max = Blt_VecMax(vector);
+ valuesPtr->values = array;
+ valuesPtr->nValues = Blt_VecLength(vector);
+ /* FindRange(valuesPtr); */
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorChangedProc --
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Graph is redrawn.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+VectorChangedProc(
+ Tcl_Interp *interp,
+ ClientData clientData,
+ Blt_VectorNotify notify)
+{
+ ElemValues *valuesPtr = clientData;
+
+ if (notify == BLT_VECTOR_NOTIFY_DESTROY) {
+ FreeDataValues(valuesPtr);
+ } else {
+ Blt_Vector *vector;
+
+ Blt_GetVectorById(interp, valuesPtr->vectorSource.vector, &vector);
+ if (FetchVectorValues(NULL, valuesPtr, vector) != TCL_OK) {
+ return;
+ }
+ }
+ {
+ Element *elemPtr = valuesPtr->elemPtr;
+ Graph *graphPtr;
+
+ graphPtr = elemPtr->obj.graphPtr;
+ graphPtr->flags |= RESET_AXES;
+ elemPtr->flags |= MAP_ITEM;
+ if (!IGNORE_ELEMENT(elemPtr)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ }
+}
+
+static int
+GetVectorData(Tcl_Interp *interp, ElemValues *valuesPtr, const char *vecName)
+{
+ Blt_Vector *vecPtr;
+ VectorDataSource *srcPtr;
+
+ srcPtr = &valuesPtr->vectorSource;
+ srcPtr->vector = Blt_AllocVectorId(interp, vecName);
+ if (Blt_GetVectorById(interp, srcPtr->vector, &vecPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (FetchVectorValues(interp, valuesPtr, vecPtr) != TCL_OK) {
+ FreeVectorSource(valuesPtr);
+ return TCL_ERROR;
+ }
+ Blt_SetVectorChangedProc(srcPtr->vector, VectorChangedProc, valuesPtr);
+ valuesPtr->type = ELEM_SOURCE_VECTOR;
+ return TCL_OK;
+}
+
+static int
+ParseValues(Tcl_Interp *interp, Tcl_Obj *objPtr, int *nValuesPtr,
+ double **arrayPtr)
+{
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *arrayPtr = NULL;
+ *nValuesPtr = 0;
+ if (objc > 0) {
+ double *array;
+ double *p;
+ int i;
+
+ array = malloc(sizeof(double) * objc);
+ if (array == NULL) {
+ Tcl_AppendResult(interp, "can't allocate new vector", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (p = array, i = 0; i < objc; i++, p++) {
+ if (Blt_ExprDoubleFromObj(interp, objv[i], p) != TCL_OK) {
+ free(array);
+ return TCL_ERROR;
+ }
+ }
+ *arrayPtr = array;
+ *nValuesPtr = objc;
+ }
+ return TCL_OK;
+}
+
+static void
+FreeDataValues(ElemValues *valuesPtr)
+{
+ switch (valuesPtr->type) {
+ case ELEM_SOURCE_VECTOR:
+ FreeVectorSource(valuesPtr); break;
+ case ELEM_SOURCE_VALUES:
+ break;
+ }
+ if (valuesPtr->values != NULL) {
+ free(valuesPtr->values);
+ }
+ valuesPtr->values = NULL;
+ valuesPtr->nValues = 0;
+ valuesPtr->type = ELEM_SOURCE_VALUES;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindRange --
+ *
+ * Find the minimum, positive minimum, and maximum values in a given
+ * vector and store the results in the vector structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Minimum, positive minimum, and maximum values are stored in the
+ * vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FindRange(ElemValues *valuesPtr)
+{
+ int i;
+ double *x;
+ double min, max;
+
+ if ((valuesPtr->nValues < 1) || (valuesPtr->values == NULL)) {
+ return; /* This shouldn't ever happen. */
+ }
+ x = valuesPtr->values;
+
+ min = DBL_MAX, max = -DBL_MAX;
+ for(i = 0; i < valuesPtr->nValues; i++) {
+ if (isfinite(x[i])) {
+ min = max = x[i];
+ break;
+ }
+ }
+ /* Initialize values to track the vector range */
+ for (/* empty */; i < valuesPtr->nValues; i++) {
+ if (isfinite(x[i])) {
+ if (x[i] < min) {
+ min = x[i];
+ } else if (x[i] > max) {
+ max = x[i];
+ }
+ }
+ }
+ valuesPtr->min = min, valuesPtr->max = max;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FindElemValuesMinimum --
+ *
+ * Find the minimum, positive minimum, and maximum values in a given
+ * vector and store the results in the vector structure.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Minimum, positive minimum, and maximum values are stored in the
+ * vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+double
+Blt_FindElemValuesMinimum(ElemValues *valuesPtr, double minLimit)
+{
+ int i;
+ double min;
+
+ min = DBL_MAX;
+ for (i = 0; i < valuesPtr->nValues; i++) {
+ double x;
+
+ x = valuesPtr->values[i];
+ if (x < 0.0) {
+ /* What do you do about negative values when using log
+ * scale values seems like a grey area. Mirror. */
+ x = -x;
+ }
+ if ((x > minLimit) && (min > x)) {
+ min = x;
+ }
+ }
+ if (min == DBL_MAX) {
+ min = minLimit;
+ }
+ return min;
+}
+
+/*ARGSUSED*/
+static void
+FreeValues(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ ElemValues *valuesPtr = (ElemValues *)(widgRec + offset);
+
+ FreeDataValues(valuesPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToValues --
+ *
+ * Given a TCL list of numeric expression representing the element
+ * values, convert into an array of double precision values. In addition,
+ * the minimum and maximum values are saved. Since elastic values are
+ * allow (values which translate to the min/max of the graph), we must
+ * try to get the non-elastic minimum and maximum.
+ *
+ * Results:
+ * The return value is a standard TCL result. The vector is passed
+ * back via the valuesPtr.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToValues(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* TCL list of expressions */
+ char *widgRec, /* Element record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ ElemValues *valuesPtr = (ElemValues *)(widgRec + offset);
+ Element *elemPtr = (Element *)widgRec;
+ Tcl_Obj **objv;
+ int objc;
+ int result;
+ const char *string;
+
+ valuesPtr->elemPtr = elemPtr;
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ elemPtr->flags |= MAP_ITEM;
+
+ /* Release the current data sources. */
+ FreeDataValues(valuesPtr);
+ if (objc == 0) {
+ return TCL_OK; /* Empty list of values. */
+ }
+ string = Tcl_GetString(objv[0]);
+ if ((objc == 1) && (Blt_VectorExists2(interp, string))) {
+ result = GetVectorData(interp, valuesPtr, string);
+ } else {
+ double *values;
+ int nValues;
+
+ result = ParseValues(interp, objPtr, &nValues, &values);
+ if (result != TCL_OK) {
+ return TCL_ERROR; /* Can't parse the values as numbers. */
+ }
+ FreeDataValues(valuesPtr);
+ if (nValues > 0) {
+ valuesPtr->values = values;
+ }
+ valuesPtr->nValues = nValues;
+ FindRange(valuesPtr);
+ valuesPtr->type = ELEM_SOURCE_VALUES;
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ValuesToObj --
+ *
+ * Convert the vector of floating point values into a TCL list.
+ *
+ * Results:
+ * The string representation of the vector is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ValuesToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ ElemValues *valuesPtr = (ElemValues *)(widgRec + offset);
+
+ switch (valuesPtr->type) {
+ case ELEM_SOURCE_VECTOR:
+ {
+ const char *vecName;
+
+ vecName = Blt_NameOfVectorId(valuesPtr->vectorSource.vector);
+ return Tcl_NewStringObj(vecName, -1);
+ }
+ case ELEM_SOURCE_VALUES:
+ {
+ Tcl_Obj *listObjPtr;
+ double *vp, *vend;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (vp = valuesPtr->values, vend = vp + valuesPtr->nValues;
+ vp < vend; vp++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(*vp));
+ }
+ return listObjPtr;
+ }
+ default:
+ abort();
+ }
+ return Tcl_NewStringObj("", 0);
+}
+
+/*ARGSUSED*/
+static void
+FreeValuePairs(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset) /* Not used. */
+{
+ Element *elemPtr = (Element *)widgRec;
+
+ FreeDataValues(&elemPtr->x);
+ FreeDataValues(&elemPtr->y);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToValuePairs --
+ *
+ * This procedure is like ObjToValues except that it interprets
+ * the list of numeric expressions as X Y coordinate pairs. The
+ * minimum and maximum for both the X and Y vectors are
+ * determined.
+ *
+ * Results:
+ * The return value is a standard TCL result. The vectors are
+ * passed back via the widget record (elemPtr).
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToValuePairs(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* TCL list of numeric expressions */
+ char *widgRec, /* Element record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Element *elemPtr = (Element *)widgRec;
+ double *values;
+ int nValues;
+ size_t newSize;
+
+ if (ParseValues(interp, objPtr, &nValues, &values) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (nValues & 1) {
+ Tcl_AppendResult(interp, "odd number of data points", (char *)NULL);
+ free(values);
+ return TCL_ERROR;
+ }
+ nValues /= 2;
+ newSize = nValues * sizeof(double);
+ FreeDataValues(&elemPtr->x); /* Release the current data sources. */
+ FreeDataValues(&elemPtr->y);
+ if (newSize > 0) {
+ double *p;
+ int i;
+
+ elemPtr->x.values = malloc(newSize);
+ elemPtr->y.values = malloc(newSize);
+ elemPtr->x.nValues = elemPtr->y.nValues = nValues;
+ for (p = values, i = 0; i < nValues; i++) {
+ elemPtr->x.values[i] = *p++;
+ elemPtr->y.values[i] = *p++;
+ }
+ free(values);
+ FindRange(&elemPtr->x);
+ FindRange(&elemPtr->y);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ValuePairsToObj --
+ *
+ * Convert pairs of floating point values in the X and Y arrays
+ * into a TCL list.
+ *
+ * Results:
+ * The return value is a string (Tcl list).
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ValuePairsToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element information record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Element *elemPtr = (Element *)widgRec;
+ Tcl_Obj *listObjPtr;
+ int i;
+ int length;
+
+ length = NUMBEROFPOINTS(elemPtr);
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (i = 0; i < length; i++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(elemPtr->x.values[i]));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(elemPtr->y.values[i]));
+ }
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToAlong --
+ *
+ * Given a TCL list of numeric expression representing the element
+ * values, convert into an array of double precision values. In
+ * addition, the minimum and maximum values are saved. Since
+ * elastic values are allow (values which translate to the
+ * min/max of the graph), we must try to get the non-elastic
+ * minimum and maximum.
+ *
+ * Results:
+ * The return value is a standard TCL result. The vector is passed
+ * back via the valuesPtr.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToAlong(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representation of value. */
+ char *widgRec, /* Widget record. */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int *intPtr = (int *)(widgRec + offset);
+ char *string;
+
+ string = Tcl_GetString(objPtr);
+ if ((string[0] == 'x') && (string[1] == '\0')) {
+ *intPtr = SEARCH_X;
+ } else if ((string[0] == 'y') && (string[1] == '\0')) {
+ *intPtr = SEARCH_Y;
+ } else if ((string[0] == 'b') && (strcmp(string, "both") == 0)) {
+ *intPtr = SEARCH_BOTH;
+ } else {
+ Tcl_AppendResult(interp, "bad along value \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AlongToObj --
+ *
+ * Convert the vector of floating point values into a TCL list.
+ *
+ * Results:
+ * The string representation of the vector is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+AlongToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int along = *(int *)(widgRec + offset);
+ Tcl_Obj *objPtr;
+
+ switch (along) {
+ case SEARCH_X:
+ objPtr = Tcl_NewStringObj("x", 1);
+ break;
+ case SEARCH_Y:
+ objPtr = Tcl_NewStringObj("y", 1);
+ break;
+ case SEARCH_BOTH:
+ objPtr = Tcl_NewStringObj("both", 4);
+ break;
+ default:
+ objPtr = Tcl_NewStringObj("unknown along value", 4);
+ break;
+ }
+ return objPtr;
+}
+
+void
+Blt_FreeStylePalette(Blt_Chain stylePalette)
+{
+ Blt_ChainLink link;
+
+ /* Skip the first slot. It contains the built-in "normal" pen of
+ * the element. */
+ link = Blt_Chain_FirstLink(stylePalette);
+ if (link != NULL) {
+ Blt_ChainLink next;
+
+ for (link = Blt_Chain_NextLink(link); link != NULL; link = next) {
+ PenStyle *stylePtr;
+
+ next = Blt_Chain_NextLink(link);
+ stylePtr = Blt_Chain_GetValue(link);
+ Blt_FreePen(stylePtr->penPtr);
+ Blt_Chain_DeleteLink(stylePalette, link);
+ }
+ }
+}
+
+/*ARGSUSED*/
+static void
+FreeStyles(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Blt_Chain stylePalette = *(Blt_Chain *)(widgRec + offset);
+
+ Blt_FreeStylePalette(stylePalette);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ObjToStyles --
+ *
+ * Parse the list of style names.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToStyles(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing style list */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Blt_Chain stylePalette = *(Blt_Chain *)(widgRec + offset);
+ Blt_ChainLink link;
+ Element *elemPtr = (Element *)(widgRec);
+ PenStyle *stylePtr;
+ Tcl_Obj **objv;
+ int objc;
+ int i;
+ size_t size = (size_t)clientData;
+
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Reserve the first entry for the "normal" pen. We'll set the
+ * style later */
+ Blt_FreeStylePalette(stylePalette);
+ link = Blt_Chain_FirstLink(stylePalette);
+ if (link == NULL) {
+ link = Blt_Chain_AllocLink(size);
+ Blt_Chain_LinkAfter(stylePalette, link, NULL);
+ }
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->penPtr = elemPtr->normalPenPtr;
+ for (i = 0; i < objc; i++) {
+ link = Blt_Chain_AllocLink(size);
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->weight.min = (double)i;
+ stylePtr->weight.max = (double)i + 1.0;
+ stylePtr->weight.range = 1.0;
+ if (GetPenStyleFromObj(interp, elemPtr->obj.graphPtr, objv[i],
+ elemPtr->obj.classId, (PenStyle *)stylePtr) != TCL_OK) {
+ Blt_FreeStylePalette(stylePalette);
+ return TCL_ERROR;
+ }
+ Blt_Chain_LinkAfter(stylePalette, link, NULL);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * StylesToObj --
+ *
+ * Convert the style information into a Tcl_Obj.
+ *
+ * Results:
+ * The string representing the style information is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+StylesToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Blt_Chain stylePalette = *(Blt_Chain *)(widgRec + offset);
+ Blt_ChainLink link;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ link = Blt_Chain_FirstLink(stylePalette);
+ if (link != NULL) {
+ /* Skip the first style (it's the default) */
+ for (link = Blt_Chain_NextLink(link); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ PenStyle *stylePtr;
+ Tcl_Obj *subListObjPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ subListObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, subListObjPtr,
+ Tcl_NewStringObj(stylePtr->penPtr->name, -1));
+ Tcl_ListObjAppendElement(interp, subListObjPtr,
+ Tcl_NewDoubleObj(stylePtr->weight.min));
+ Tcl_ListObjAppendElement(interp, subListObjPtr,
+ Tcl_NewDoubleObj(stylePtr->weight.max));
+ Tcl_ListObjAppendElement(interp, listObjPtr, subListObjPtr);
+ }
+ }
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_StyleMap --
+ *
+ * Creates an array of style indices and fills it based on the weight
+ * of each data point.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the index array.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+PenStyle **
+Blt_StyleMap(Element *elemPtr)
+{
+ int i;
+ int nWeights; /* Number of weights to be examined.
+ * If there are more data points than
+ * weights, they will default to the
+ * normal pen. */
+
+ PenStyle **dataToStyle; /* Directory of styles. Each array
+ * element represents the style for
+ * the data point at that index */
+ Blt_ChainLink link;
+ PenStyle *stylePtr;
+ double *w; /* Weight vector */
+ int nPoints;
+
+ nPoints = NUMBEROFPOINTS(elemPtr);
+ nWeights = MIN(elemPtr->w.nValues, nPoints);
+ w = elemPtr->w.values;
+ link = Blt_Chain_FirstLink(elemPtr->stylePalette);
+ stylePtr = Blt_Chain_GetValue(link);
+
+ /*
+ * Create a style mapping array (data point index to style),
+ * initialized to the default style.
+ */
+ dataToStyle = malloc(nPoints * sizeof(PenStyle *));
+ for (i = 0; i < nPoints; i++) {
+ dataToStyle[i] = stylePtr;
+ }
+
+ for (i = 0; i < nWeights; i++) {
+ for (link = Blt_Chain_LastLink(elemPtr->stylePalette); link != NULL;
+ link = Blt_Chain_PrevLink(link)) {
+ stylePtr = Blt_Chain_GetValue(link);
+
+ if (stylePtr->weight.range > 0.0) {
+ double norm;
+
+ norm = (w[i] - stylePtr->weight.min) / stylePtr->weight.range;
+ if (((norm - 1.0) <= DBL_EPSILON) &&
+ (((1.0 - norm) - 1.0) <= DBL_EPSILON)) {
+ dataToStyle[i] = stylePtr;
+ break; /* Done: found range that matches. */
+ }
+ }
+ }
+ }
+ return dataToStyle;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetIndex --
+ *
+ * Given a string representing the index of a pair of x,y
+ * coordinates, return the numeric index.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+GetIndex(Tcl_Interp *interp, Element *elemPtr, Tcl_Obj *objPtr, int *indexPtr)
+{
+ char *string;
+
+ string = Tcl_GetString(objPtr);
+ if ((*string == 'e') && (strcmp("end", string) == 0)) {
+ *indexPtr = NUMBEROFPOINTS(elemPtr) - 1;
+ } else if (Blt_ExprIntFromObj(interp, objPtr, indexPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetElement --
+ *
+ * Find the element represented the given name, returning a pointer to
+ * its data structure via elemPtrPtr.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetElement(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ Element **elemPtrPtr)
+{
+ Blt_HashEntry *hPtr;
+ char *name;
+
+ name = Tcl_GetString(objPtr);
+ hPtr = Blt_FindHashEntry(&graphPtr->elements.table, name);
+ if (hPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find element \"", name,
+ "\" in \"", Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ *elemPtrPtr = Blt_GetHashValue(hPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyElement --
+ *
+ * Add a new element to the graph.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DestroyElement(Element *elemPtr)
+{
+ Graph *graphPtr = elemPtr->obj.graphPtr;
+
+ Blt_DeleteBindings(graphPtr->bindTable, elemPtr);
+ Blt_Legend_RemoveElement(graphPtr, elemPtr);
+
+ Blt_FreeOptions(elemPtr->configSpecs, (char *)elemPtr,graphPtr->display, 0);
+ /*
+ * Call the element's own destructor to release the memory and
+ * resources allocated for it.
+ */
+ (*elemPtr->procsPtr->destroyProc) (graphPtr, elemPtr);
+
+ /* Remove it also from the element display list */
+ if (elemPtr->link != NULL) {
+ Blt_Chain_DeleteLink(graphPtr->elements.displayList, elemPtr->link);
+ if (!IGNORE_ELEMENT(elemPtr)) {
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ }
+ /* Remove the element for the graph's hash table of elements */
+ if (elemPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&graphPtr->elements.table, elemPtr->hashPtr);
+ }
+ if (elemPtr->obj.name != NULL) {
+ free((void*)(elemPtr->obj.name));
+ }
+ if (elemPtr->label != NULL) {
+ free((void*)(elemPtr->label));
+ }
+ free(elemPtr);
+}
+
+static void FreeElement(char* data)
+{
+ Element *elemPtr = (Element *)data;
+ DestroyElement(elemPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateElement --
+ *
+ * Add a new element to the graph.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+CreateElement(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv, ClassId classId)
+{
+ Element *elemPtr;
+ Blt_HashEntry *hPtr;
+ int isNew;
+ char *string;
+
+ string = Tcl_GetString(objv[3]);
+ if (string[0] == '-') {
+ Tcl_AppendResult(graphPtr->interp, "name of element \"", string,
+ "\" can't start with a '-'", (char *)NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Blt_CreateHashEntry(&graphPtr->elements.table, string, &isNew);
+ if (!isNew) {
+ Tcl_AppendResult(interp, "element \"", string,
+ "\" already exists in \"", Tcl_GetString(objv[0]),
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (classId == CID_ELEM_BAR) {
+ elemPtr = Blt_BarElement(graphPtr, string, classId);
+ } else {
+ /* Stripcharts are line graphs with some options enabled. */
+ elemPtr = Blt_LineElement(graphPtr, string, classId);
+ }
+ assert(elemPtr->configSpecs != NULL);
+ elemPtr->hashPtr = hPtr;
+ Blt_SetHashValue(hPtr, elemPtr);
+
+ if (Blt_ConfigureComponentFromObj(interp, graphPtr->tkwin,
+ elemPtr->obj.name, "Element", elemPtr->configSpecs, objc - 4, objv + 4,
+ (char *)elemPtr, 0) != TCL_OK) {
+ DestroyElement(elemPtr);
+ return TCL_ERROR;
+ }
+ (*elemPtr->procsPtr->configProc) (graphPtr, elemPtr);
+ elemPtr->link = Blt_Chain_Append(graphPtr->elements.displayList, elemPtr);
+ graphPtr->flags |= CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ elemPtr->flags |= MAP_ITEM;
+ graphPtr->flags |= RESET_AXES;
+ Tcl_SetObjResult(interp, objv[3]);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DestroyElements --
+ *
+ * Removes all the graph's elements. This routine is called when
+ * the graph is destroyed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory allocated for the graph's elements is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DestroyElements(Graph *graphPtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+ Element *elemPtr;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.table, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ elemPtr = Blt_GetHashValue(hPtr);
+ elemPtr->hashPtr = NULL;
+ DestroyElement(elemPtr);
+ }
+ Blt_DeleteHashTable(&graphPtr->elements.table);
+ Blt_DeleteHashTable(&graphPtr->elements.tagTable);
+ Blt_Chain_Destroy(graphPtr->elements.displayList);
+}
+
+void
+Blt_ConfigureElements(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ (*elemPtr->procsPtr->configProc) (graphPtr, elemPtr);
+ }
+}
+
+void
+Blt_MapElements(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ if (graphPtr->mode != BARS_INFRONT) {
+ Blt_ResetBarGroups(graphPtr);
+ }
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (IGNORE_ELEMENT(elemPtr)) {
+ continue;
+ }
+ if ((graphPtr->flags & MAP_ALL) || (elemPtr->flags & MAP_ITEM)) {
+ (*elemPtr->procsPtr->mapProc) (graphPtr, elemPtr);
+ elemPtr->flags &= ~MAP_ITEM;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawElements --
+ *
+ * Calls the individual element drawing routines for each
+ * element.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Elements are drawn into the drawable (pixmap) which will
+ * eventually be displayed in the graph window.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawElements(Graph *graphPtr, Drawable drawable)
+{
+ Blt_ChainLink link;
+
+ /* Draw with respect to the stacking order. */
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((elemPtr->flags & (HIDE|DELETE_PENDING)) == 0) {
+ (*elemPtr->procsPtr->drawNormalProc)(graphPtr, drawable, elemPtr);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawActiveElements --
+ *
+ * Calls the individual element drawing routines to display
+ * the active colors for each element.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Elements are drawn into the drawable (pixmap) which will
+ * eventually be displayed in the graph window.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawActiveElements(Graph *graphPtr, Drawable drawable)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((elemPtr->flags & (HIDE|ACTIVE|DELETE_PENDING)) == ACTIVE) {
+ (*elemPtr->procsPtr->drawActiveProc)(graphPtr, drawable, elemPtr);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ElementsToPostScript --
+ *
+ * Generates PostScript output for each graph element in the
+ * element display list.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ElementsToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->flags & (HIDE|DELETE_PENDING)) {
+ continue;
+ }
+ /* Comment the PostScript to indicate the start of the element */
+ Blt_Ps_Format(ps, "\n%% Element \"%s\"\n\n", elemPtr->obj.name);
+ (*elemPtr->procsPtr->printNormalProc) (graphPtr, ps, elemPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ActiveElementsToPostScript --
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ActiveElementsToPostScript( Graph *graphPtr, Blt_Ps ps)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if ((elemPtr->flags & (DELETE_PENDING|HIDE|ACTIVE)) == ACTIVE) {
+ Blt_Ps_Format(ps, "\n%% Active Element \"%s\"\n\n",
+ elemPtr->obj.name);
+ (*elemPtr->procsPtr->printActiveProc)(graphPtr, ps, elemPtr);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ActivateOp --
+ *
+ * Marks data points of elements (given by their index) as active.
+ *
+ * Results:
+ * Returns TCL_OK if no errors occurred.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ActivateOp(
+ Graph *graphPtr, /* Graph widget */
+ Tcl_Interp *interp, /* Interpreter to report errors to */
+ int objc, /* Number of element names */
+ Tcl_Obj *const *objv) /* List of element names */
+{
+ Element *elemPtr;
+ int i;
+ int *indices;
+ int nIndices;
+
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ /* List all the currently active elements */
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.table, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ elemPtr = Blt_GetHashValue(hPtr);
+ if (elemPtr->flags & ACTIVE) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(elemPtr->obj.name, -1));
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ if (Blt_GetElement(interp, graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ elemPtr->flags |= ACTIVE | ACTIVE_PENDING;
+
+ indices = NULL;
+ nIndices = -1;
+ if (objc > 4) {
+ int *activePtr;
+
+ nIndices = objc - 4;
+ activePtr = indices = malloc(sizeof(int) * nIndices);
+ for (i = 4; i < objc; i++) {
+ if (GetIndex(interp, elemPtr, objv[i], activePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ activePtr++;
+ }
+ }
+ if (elemPtr->activeIndices != NULL) {
+ free(elemPtr->activeIndices);
+ }
+ elemPtr->nActiveIndices = nIndices;
+ elemPtr->activeIndices = indices;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+ClientData
+Blt_MakeElementTag(Graph *graphPtr, const char *tagName)
+{
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&graphPtr->elements.tagTable, tagName, &isNew);
+ return Blt_GetHashKey(&graphPtr->elements.tagTable, hPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BindOp --
+ *
+ * .g element bind elemName sequence command
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+BindOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+ char *tagName;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.tagTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ tagName = Blt_GetHashKey(&graphPtr->elements.tagTable, hPtr);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(tagName, -1));
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->bindTable,
+ Blt_MakeElementTag(graphPtr, Tcl_GetString(objv[3])),
+ objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateOp --
+ *
+ * Add a new element to the graph (using the default type of the
+ * graph).
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+CreateOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv,
+ ClassId classId)
+{
+ return CreateElement(graphPtr, interp, objc, objv, classId);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+CgetOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv)
+{
+ Element *elemPtr;
+
+ if (Blt_GetElement(interp, graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ if (Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, elemPtr->configSpecs,
+ (char *)elemPtr, objv[4], 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClosestOp --
+ *
+ * Find the element closest to the specified screen coordinates.
+ * Options:
+ * -halo Consider points only with this maximum distance
+ * from the picked coordinate.
+ * -interpolate Find closest point along element traces, not just
+ * data points.
+ * -along
+ *
+ * Results:
+ * A standard TCL result. If an element could be found within
+ * the halo distance, the interpreter result is "1", otherwise
+ * "0". If a closest element exists, the designated TCL array
+ * variable will be set with the following information:
+ *
+ * 1) the element name,
+ * 2) the index of the closest point,
+ * 3) the distance (in screen coordinates) from the picked X-Y
+ * coordinate and the closest point,
+ * 4) the X coordinate (graph coordinate) of the closest point,
+ * 5) and the Y-coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Blt_ConfigSpec closestSpecs[] = {
+ {BLT_CONFIG_PIXELS_NNEG, "-halo", (char *)NULL, (char *)NULL,
+ (char *)NULL, Blt_Offset(ClosestSearch, halo), 0},
+ {BLT_CONFIG_BOOLEAN, "-interpolate", (char *)NULL, (char *)NULL,
+ (char *)NULL, Blt_Offset(ClosestSearch, mode), 0 },
+ {BLT_CONFIG_CUSTOM, "-along", (char *)NULL, (char *)NULL,
+ (char *)NULL, Blt_Offset(ClosestSearch, along), 0, &alongOption},
+ {BLT_CONFIG_END, (char *)NULL, (char *)NULL, (char *)NULL,
+ (char *)NULL, 0, 0}
+};
+
+static int
+ClosestOp(
+ Graph *graphPtr, /* Graph widget */
+ Tcl_Interp *interp, /* Interpreter to report results to */
+ int objc, /* Number of element names */
+ Tcl_Obj *const *objv) /* List of element names */
+{
+ Element *elemPtr;
+ ClosestSearch search;
+ int i, x, y;
+ char *string;
+
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) {
+ Tcl_AppendResult(interp, ": bad window x-coordinate", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK) {
+ Tcl_AppendResult(interp, ": bad window y-coordinate", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 5; i < objc; i += 2) { /* Count switches-value pairs */
+ string = Tcl_GetString(objv[i]);
+ if ((string[0] != '-') ||
+ ((string[1] == '-') && (string[2] == '\0'))) {
+ break;
+ }
+ }
+ if (i > objc) {
+ i = objc;
+ }
+
+ search.mode = SEARCH_POINTS;
+ search.halo = graphPtr->halo;
+ search.index = -1;
+ search.along = SEARCH_BOTH;
+ search.x = x;
+ search.y = y;
+
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, closestSpecs, i - 5,
+ objv + 5, (char *)&search, BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
+ return TCL_ERROR; /* Error occurred processing an option. */
+ }
+ if (i < objc) {
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ i++; /* Skip "--" */
+ }
+ }
+ search.dist = (double)(search.halo + 1);
+
+ if (i < objc) {
+ for ( /* empty */ ; i < objc; i++) {
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ if (IGNORE_ELEMENT(elemPtr)) {
+ continue;
+ }
+ if (elemPtr->flags & (HIDE|MAP_ITEM)) {
+ continue;
+ }
+ (*elemPtr->procsPtr->closestProc) (graphPtr, elemPtr, &search);
+ }
+ } else {
+ Blt_ChainLink link;
+
+ /*
+ * Find the closest point from the set of displayed elements,
+ * searching the display list from back to front. That way if
+ * the points from two different elements overlay each other
+ * exactly, the last one picked will be the topmost.
+ */
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->flags & (HIDE|MAP_ITEM|DELETE_PENDING)) {
+ continue;
+ }
+ (*elemPtr->procsPtr->closestProc) (graphPtr, elemPtr, &search);
+ }
+ }
+ if (search.dist < (double)search.halo) {
+ Tcl_Obj *listObjPtr;
+ /*
+ * Return a list of name value pairs.
+ */
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("name", -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(search.elemPtr->obj.name, -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("index", -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(search.index));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("x", -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(search.point.x));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("y", -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(search.point.y));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj("dist", -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(search.dist));
+ Tcl_SetObjResult(interp, listObjPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Sets the element specifications by the given the command line
+ * arguments and calls the element specification configuration
+ * routine. If zero or one command line options are given, only
+ * information about the option(s) is returned in interp->result.
+ * If the element configuration has changed and the element is
+ * currently displayed, the axis limits are updated and
+ * recomputed.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new display list.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ int nNames, nOpts;
+ Tcl_Obj *const *options;
+ int i;
+
+ /* Figure out where the option value pairs begin */
+ objc -= 3;
+ objv += 3;
+ for (i = 0; i < objc; i++) {
+ Element *elemPtr;
+ char *string;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ break;
+ }
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ }
+ nNames = i; /* Number of element names specified */
+ nOpts = objc - i; /* Number of options specified */
+ options = objv + nNames; /* Start of options in objv */
+
+ for (i = 0; i < nNames; i++) {
+ Element *elemPtr;
+ int flags;
+
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flags = BLT_CONFIG_OBJV_ONLY;
+ if (nOpts == 0) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ elemPtr->configSpecs, (char *)elemPtr, (Tcl_Obj *)NULL, flags);
+ } else if (nOpts == 1) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ elemPtr->configSpecs, (char *)elemPtr, options[0], flags);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin,
+ elemPtr->configSpecs, nOpts, options, (char *)elemPtr, flags)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((*elemPtr->procsPtr->configProc) (graphPtr, elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Failed to configure element */
+ }
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-hide", (char *)NULL)) {
+ graphPtr->flags |= RESET_AXES;
+ elemPtr->flags |= MAP_ITEM;
+ }
+ /* If data points or axes have changed, reset the axes (may
+ * affect autoscaling) and recalculate the screen points of
+ * the element. */
+
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-*data", "-map*", "-x",
+ "-y", (char *)NULL)) {
+ graphPtr->flags |= RESET_WORLD;
+ elemPtr->flags |= MAP_ITEM;
+ }
+ /* The new label may change the size of the legend */
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-label", (char *)NULL)) {
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ }
+ }
+ /* Update the pixmap if any configuration option changed */
+ graphPtr->flags |= CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeactivateOp --
+ *
+ * Clears the active bit for the named elements.
+ *
+ * Results:
+ * Returns TCL_OK if no errors occurred.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+DeactivateOp(
+ Graph *graphPtr, /* Graph widget */
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Number of element names */
+ Tcl_Obj *const *objv) /* List of element names */
+{
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ Element *elemPtr;
+
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ elemPtr->flags &= ~(ACTIVE | ACTIVE_PENDING);
+ if (elemPtr->activeIndices != NULL) {
+ free(elemPtr->activeIndices);
+ elemPtr->activeIndices = NULL;
+ }
+ elemPtr->nActiveIndices = 0;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteOp --
+ *
+ * Delete the named elements from the graph.
+ *
+ * Results:
+ * TCL_ERROR is returned if any of the named elements can not be
+ * found. Otherwise TCL_OK is returned;
+ *
+ * Side Effects:
+ * If the element is currently displayed, the plotting area of
+ * the graph is redrawn. Memory and resources allocated by the
+ * elements are released.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+DeleteOp(
+ Graph *graphPtr, /* Graph widget */
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Number of element names */
+ Tcl_Obj *const *objv) /* List of element names */
+{
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ Element *elemPtr;
+
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ elemPtr->flags |= DELETE_PENDING;
+ Tcl_EventuallyFree(elemPtr, FreeElement);
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ExistsOp --
+ *
+ * Indicates if the named element exists in the graph.
+ *
+ * Results:
+ * The return value is a standard TCL result. The interpreter
+ * result will contain "1" or "0".
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ExistsOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv)
+{
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&graphPtr->elements.table, Tcl_GetString(objv[3]));
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (hPtr != NULL));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetOp --
+ *
+ * Returns the name of the picked element (using the element
+ * bind operation). Right now, the only name accepted is
+ * "current".
+ *
+ * Results:
+ * A standard TCL result. The interpreter result will contain
+ * the name of the element.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+GetOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv)
+{
+ char *string;
+
+ string = Tcl_GetString(objv[3]);
+ if ((string[0] == 'c') && (strcmp(string, "current") == 0)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_GetCurrentItem(graphPtr->bindTable);
+ /* Report only on elements. */
+ if ((elemPtr != NULL) && ((elemPtr->flags & DELETE_PENDING) == 0) &&
+ (elemPtr->obj.classId >= CID_ELEM_BAR) &&
+ (elemPtr->obj.classId <= CID_ELEM_LINE)) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name,-1);
+ }
+ }
+ return TCL_OK;
+}
+
+static Tcl_Obj *
+DisplayListObj(Graph *graphPtr)
+{
+ Tcl_Obj *listObjPtr;
+ Blt_ChainLink link;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ Tcl_Obj *objPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(graphPtr->interp, listObjPtr, objPtr);
+ }
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LowerOp --
+ *
+ * Lowers the named elements to the bottom of the display list.
+ *
+ * Results:
+ * A standard TCL result. The interpreter result will contain the new
+ * display list of element names.
+ *
+ * .g element lower elem ?elem...?
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+LowerOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_Chain chain;
+ Blt_ChainLink link, next;
+ int i;
+
+ /* Move the links of lowered elements out of the display list into
+ * a temporary list. */
+ chain = Blt_Chain_Create();
+ for (i = 3; i < objc; i++) {
+ Element *elemPtr;
+
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ Blt_Chain_UnlinkLink(graphPtr->elements.displayList, elemPtr->link);
+ Blt_Chain_LinkAfter(chain, elemPtr->link, NULL);
+ }
+ /* Append the links to end of the display list. */
+ for (link = Blt_Chain_FirstLink(chain); link != NULL; link = next) {
+ next = Blt_Chain_NextLink(link);
+ Blt_Chain_UnlinkLink(chain, link);
+ Blt_Chain_LinkAfter(graphPtr->elements.displayList, link, NULL);
+ }
+ Blt_Chain_Destroy(chain);
+ Tcl_SetObjResult(interp, DisplayListObj(graphPtr));
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NamesOp --
+ *
+ * Returns the names of the elements is the graph matching
+ * one of more patterns provided. If no pattern arguments
+ * are given, then all element names will be returned.
+ *
+ * Results:
+ * The return value is a standard TCL result. The interpreter
+ * result will contain a TCL list of the element names.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+NamesOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.table, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Element *elemPtr;
+ Tcl_Obj *objPtr;
+
+ elemPtr = Blt_GetHashValue(hPtr);
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ } else {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.table, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Element *elemPtr;
+ int i;
+
+ elemPtr = Blt_GetHashValue(hPtr);
+ for (i = 3; i < objc; i++) {
+ if (Tcl_StringMatch(elemPtr->obj.name,Tcl_GetString(objv[i]))) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ break;
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RaiseOp --
+ *
+ * Reset the element within the display list.
+ *
+ * Results:
+ * The return value is a standard TCL result. The interpreter
+ * result will contain the new display list of element names.
+ *
+ * .g element raise ?elem...?
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RaiseOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_Chain chain;
+ Blt_ChainLink link, prev;
+ int i;
+
+ /* Move the links of lowered elements out of the display list into
+ * a temporary list. */
+ chain = Blt_Chain_Create();
+ for (i = 3; i < objc; i++) {
+ Element *elemPtr;
+
+ if (Blt_GetElement(interp, graphPtr, objv[i], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ Blt_Chain_UnlinkLink(graphPtr->elements.displayList, elemPtr->link);
+ Blt_Chain_LinkAfter(chain, elemPtr->link, NULL);
+ }
+ /* Prepend the links to beginning of the display list in reverse order. */
+ for (link = Blt_Chain_LastLink(chain); link != NULL; link = prev) {
+ prev = Blt_Chain_PrevLink(link);
+ Blt_Chain_UnlinkLink(chain, link);
+ Blt_Chain_LinkBefore(graphPtr->elements.displayList, link, NULL);
+ }
+ Blt_Chain_Destroy(chain);
+ Tcl_SetObjResult(interp, DisplayListObj(graphPtr));
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ShowOp --
+ *
+ * Queries or resets the element display list.
+ *
+ * Results:
+ * The return value is a standard TCL result. The interpreter
+ * result will contain the new display list of element names.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ShowOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ if (objc == 4) {
+ Blt_Chain chain;
+ Blt_ChainLink link;
+ Tcl_Obj **elem;
+ int i, n;
+
+ if (Tcl_ListObjGetElements(interp, objv[3], &n, &elem) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Collect the named elements into a list. */
+ chain = Blt_Chain_Create();
+ for (i = 0; i < n; i++) {
+ Element *elemPtr; /* Element information record */
+
+ if (Blt_GetElement(interp, graphPtr, elem[i], &elemPtr) != TCL_OK) {
+ Blt_Chain_Destroy(chain);
+ return TCL_ERROR;
+ }
+ Blt_Chain_Append(chain, elemPtr);
+ }
+ /* Clear the links from the currently displayed elements. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ elemPtr->link = NULL;
+ }
+ Blt_Chain_Destroy(graphPtr->elements.displayList);
+ graphPtr->elements.displayList = chain;
+ /* Set links on all the displayed elements. */
+ for (link = Blt_Chain_FirstLink(chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ elemPtr->link = link;
+ }
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ Tcl_SetObjResult(interp, DisplayListObj(graphPtr));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TypeOp --
+ *
+ * Returns the name of the type of the element given by some
+ * element name.
+ *
+ * Results:
+ * A standard TCL result. Returns the type of the element in
+ * interp->result. If the identifier given doesn't represent an
+ * element, then an error message is left in interp->result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TypeOp(
+ Graph *graphPtr, /* Graph widget */
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv) /* Element name */
+{
+ Element *elemPtr;
+ const char *string;
+
+ if (Blt_GetElement(interp, graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR; /* Can't find named element */
+ }
+ switch (elemPtr->obj.classId) {
+ case CID_ELEM_BAR: string = "bar"; break;
+ case CID_ELEM_LINE: string = "line"; break;
+ default: string = "???"; break;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), string, -1);
+ return TCL_OK;
+}
+
+/*
+ * Global routines:
+ */
+static Blt_OpSpec elemOps[] = {
+ {"activate", 1, ActivateOp, 3, 0, "?elemName? ?index...?",},
+ {"bind", 1, BindOp, 3, 6, "elemName sequence command",},
+ {"cget", 2, CgetOp, 5, 5, "elemName option",},
+ {"closest", 2, ClosestOp, 5, 0,
+ "x y ?option value?... ?elemName?...",},
+ {"configure", 2, ConfigureOp, 4, 0,
+ "elemName ?elemName?... ?option value?...",},
+ {"create", 2, CreateOp, 4, 0, "elemName ?option value?...",},
+ {"deactivate", 3, DeactivateOp, 3, 0, "?elemName?...",},
+ {"delete", 3, DeleteOp, 3, 0, "?elemName?...",},
+ {"exists", 1, ExistsOp, 4, 4, "elemName",},
+ {"get", 1, GetOp, 4, 4, "name",},
+ {"lower", 1, LowerOp, 3, 0, "?elemName?...",},
+ {"names", 1, NamesOp, 3, 0, "?pattern?...",},
+ {"raise", 1, RaiseOp, 3, 0, "?elemName?...",},
+ {"show", 1, ShowOp, 3, 4, "?elemList?",},
+ {"type", 1, TypeOp, 4, 4, "elemName",},
+};
+static int numElemOps = sizeof(elemOps) / sizeof(Blt_OpSpec);
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ElementOp --
+ *
+ * This procedure is invoked to process the TCL command that
+ * corresponds to a widget managed by this module. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ElementOp(
+ Graph *graphPtr, /* Graph widget record */
+ Tcl_Interp *interp,
+ int objc, /* # arguments */
+ Tcl_Obj *const *objv, /* Argument list */
+ ClassId classId)
+{
+ void *ptr;
+ int result;
+
+ ptr = Blt_GetOpFromObj(interp, numElemOps, elemOps, BLT_OP_ARG2,
+ objc, objv, 0);
+ if (ptr == NULL) {
+ return TCL_ERROR;
+ }
+ if (ptr == CreateOp) {
+ result = CreateOp(graphPtr, interp, objc, objv, classId);
+ } else {
+ GraphElementProc *proc;
+
+ proc = ptr;
+ result = (*proc) (graphPtr, interp, objc, objv);
+ }
+ return result;
+}
diff --git a/tlt3.0/bltGrElem.h b/tlt3.0/bltGrElem.h
new file mode 100644
index 0000000..012e071
--- /dev/null
+++ b/tlt3.0/bltGrElem.h
@@ -0,0 +1,251 @@
+
+/*
+ * bltGrElem.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GR_ELEM_H
+#define _BLT_GR_ELEM_H
+
+#include <bltVector.h>
+
+#define ELEM_SOURCE_VALUES 0
+#define ELEM_SOURCE_VECTOR 1
+
+#define SEARCH_X 0
+#define SEARCH_Y 1
+#define SEARCH_BOTH 2
+
+#define SHOW_NONE 0
+#define SHOW_X 1
+#define SHOW_Y 2
+#define SHOW_BOTH 3
+
+#define SEARCH_POINTS 0 /* Search for closest data point. */
+#define SEARCH_TRACES 1 /* Search for closest point on trace.
+ * Interpolate the connecting line segments if
+ * necessary. */
+#define SEARCH_AUTO 2 /* Automatically determine whether to search
+ * for data points or traces. Look for traces
+ * if the linewidth is > 0 and if there is
+ * more than one data point. */
+
+#define LABEL_ACTIVE (1<<9) /* Non-zero indicates that the element's entry
+ * in the legend should be drawn in its active
+ * foreground and background colors. */
+#define SCALE_SYMBOL (1<<10)
+
+#define NUMBEROFPOINTS(e) MIN((e)->x.nValues, (e)->y.nValues)
+
+#define NORMALPEN(e) ((((e)->normalPenPtr == NULL) ? \
+ (e)->builtinPenPtr : \
+ (e)->normalPenPtr))
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Weight --
+ *
+ * Designates a range of values by a minimum and maximum limit.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ double min, max, range;
+} Weight;
+
+#define SetRange(l) \
+ ((l).range = ((l).max > (l).min) ? ((l).max - (l).min) : DBL_EPSILON)
+#define SetScale(l) \
+ ((l).scale = 1.0 / (l).range)
+#define SetWeight(l, lo, hi) \
+ ((l).min = (lo), (l).max = (hi), SetRange(l))
+
+typedef struct {
+ Segment2d *segments; /* Point to start of this pen's X-error bar
+ * segments in the element's array. */
+ int nSegments;
+} ErrorBarSegments;
+
+/*
+ * An element has one or more vectors plus several attributes, such as line
+ * style, thickness, color, and symbol type. It has an identifier which
+ * distinguishes it among the list of all elements.
+ */
+typedef struct {
+ Weight weight; /* Weight range where this pen is valid. */
+ Pen *penPtr; /* Pen to use. */
+} PenStyle;
+
+
+typedef struct {
+ XColor *color; /* Color of error bar */
+ int lineWidth; /* Width of the error bar segments. */
+ GC gc;
+ int show; /* Flags for errorbars: none, x, y, or both */
+} ErrorBarAttributes;
+
+typedef struct {
+ /* Inputs */
+ int halo; /* Maximal screen distance a candidate point
+ * can be from the sample window coordinate */
+
+ int mode; /* Indicates whether to find the closest data
+ * point or the closest point on the trace by
+ * interpolating the line segments. Can also
+ * be SEARCH_AUTO, indicating to choose how to
+ * search.*/
+
+ int x, y; /* Screen coordinates of test point */
+
+ int along; /* Indicates to let search run along a
+ * particular axis: x, y, or both. */
+
+ /* Outputs */
+ Element *elemPtr; /* Name of the closest element */
+
+ Point2d point; /* Graph coordinates of closest point */
+
+ int index; /* Index of closest data point */
+
+ double dist; /* Distance in screen coordinates */
+
+} ClosestSearch;
+
+typedef void (ElementDrawProc) (Graph *graphPtr, Drawable drawable,
+ Element *elemPtr);
+
+typedef void (ElementToPostScriptProc) (Graph *graphPtr, Blt_Ps ps,
+ Element *elemPtr);
+
+typedef void (ElementDestroyProc) (Graph *graphPtr, Element *elemPtr);
+
+typedef int (ElementConfigProc) (Graph *graphPtr, Element *elemPtr);
+
+typedef void (ElementMapProc) (Graph *graphPtr, Element *elemPtr);
+
+typedef void (ElementExtentsProc) (Element *elemPtr, Region2d *extsPtr);
+
+typedef void (ElementClosestProc) (Graph *graphPtr, Element *elemPtr,
+ ClosestSearch *searchPtr);
+
+typedef void (ElementDrawSymbolProc) (Graph *graphPtr, Drawable drawable,
+ Element *elemPtr, int x, int y, int symbolSize);
+
+typedef void (ElementSymbolToPostScriptProc) (Graph *graphPtr,
+ Blt_Ps ps, Element *elemPtr, double x, double y, int symSize);
+
+typedef struct {
+ ElementClosestProc *closestProc;
+ ElementConfigProc *configProc;
+ ElementDestroyProc *destroyProc;
+ ElementDrawProc *drawActiveProc;
+ ElementDrawProc *drawNormalProc;
+ ElementDrawSymbolProc *drawSymbolProc;
+ ElementExtentsProc *extentsProc;
+ ElementToPostScriptProc *printActiveProc;
+ ElementToPostScriptProc *printNormalProc;
+ ElementSymbolToPostScriptProc *printSymbolProc;
+ ElementMapProc *mapProc;
+} ElementProcs;
+
+typedef struct {
+ Blt_VectorId vector;
+} VectorDataSource;
+
+/*
+ * The data structure below contains information pertaining to a line vector.
+ * It consists of an array of floating point data values and for convenience,
+ * the number and minimum/maximum values.
+ */
+typedef struct {
+ int type; /* Selects the type of data populating this
+ * vector: ELEM_SOURCE_VECTOR,
+ * ELEM_SOURCE_TABLE, or ELEM_SOURCE_VALUES
+ */
+ Element *elemPtr; /* Element associated with vector. */
+ VectorDataSource vectorSource;
+ double *values;
+ int nValues;
+ int arraySize;
+ double min, max;
+} ElemValues;
+
+
+struct _Element {
+ GraphObj obj; /* Must be first field in element. */
+ unsigned int flags;
+ Blt_HashEntry *hashPtr;
+
+ /* Fields specific to elements. */
+ const char *label; /* Label displayed in legend */
+ unsigned short row, col; /* Position of the entry in the
+ * legend. */
+ int legendRelief; /* Relief of label in legend. */
+ Axis2d axes; /* X-axis and Y-axis mapping the
+ * element */
+ ElemValues x, y, w; /* Contains array of floating point
+ * graph coordinate values. Also holds
+ * min/max and the number of
+ * coordinates */
+ int *activeIndices; /* Array of indices (malloc-ed) which
+ * indicate which data points are
+ * active (drawn with "active"
+ * colors). */
+ int nActiveIndices; /* Number of active data points.
+ * Special case: if nActiveIndices < 0
+ * and the active bit is set in
+ * "flags", then all data points are
+ * drawn active. */
+ ElementProcs *procsPtr;
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications. */
+ Pen *activePenPtr; /* Standard Pens */
+ Pen *normalPenPtr;
+ Pen *builtinPenPtr;
+ Blt_Chain stylePalette; /* Palette of pens. */
+
+ /* Symbol scaling */
+ int scaleSymbols; /* If non-zero, the symbols will scale
+ * in size as the graph is zoomed
+ * in/out. */
+ double xRange, yRange; /* Initial X-axis and Y-axis ranges:
+ * used to scale the size of element's
+ * symbol. */
+ int state;
+ Blt_ChainLink link; /* Element's link in display list. */
+};
+
+
+extern double Blt_FindElemValuesMinimum(ElemValues *vecPtr, double minLimit);
+extern void Blt_ResizeStatusArray(Element *elemPtr, int nPoints);
+extern int Blt_GetPenStyle(Graph *graphPtr, char *name, size_t classId,
+ PenStyle *stylePtr);
+extern void Blt_FreeStylePalette (Blt_Chain stylePalette);
+extern PenStyle **Blt_StyleMap (Element *elemPtr);
+extern void Blt_MapErrorBars(Graph *graphPtr, Element *elemPtr,
+ PenStyle **dataToStyle);
+extern void Blt_FreeDataValues(ElemValues *evPtr);
+extern int Blt_GetElement(Tcl_Interp *interp, Graph *graphPtr,
+ Tcl_Obj *objPtr, Element **elemPtrPtr);
+
+#endif /* _BLT_GR_ELEM_H */
diff --git a/tlt3.0/bltGrHairs.c b/tlt3.0/bltGrHairs.c
new file mode 100644
index 0000000..4f1994f
--- /dev/null
+++ b/tlt3.0/bltGrHairs.c
@@ -0,0 +1,535 @@
+
+/*
+ * bltGrHairs.c --
+ *
+ * This module implements crosshairs for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+
+typedef int (GraphCrosshairProc)(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Crosshairs
+ *
+ * Contains the line segments positions and graphics context used
+ * to simulate crosshairs (by XORing) on the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+struct _Crosshairs {
+
+ XPoint hotSpot; /* Hot spot for crosshairs */
+ int visible; /* Internal state of crosshairs. If non-zero,
+ * crosshairs are displayed. */
+ int hidden; /* If non-zero, crosshairs are not displayed.
+ * This is not necessarily consistent with the
+ * internal state variable. This is true when
+ * the hot spot is off the graph. */
+ Blt_Dashes dashes; /* Dashstyle of the crosshairs. This represents
+ * an array of alternatingly drawn pixel
+ * values. If NULL, the hairs are drawn as a
+ * solid line */
+ int lineWidth; /* Width of the simulated crosshair lines */
+ XSegment segArr[2]; /* Positions of line segments representing the
+ * simulated crosshairs. */
+ XColor *colorPtr; /* Foreground color of crosshairs */
+ GC gc; /* Graphics context for crosshairs. Set to
+ * GXxor to not require redraws of graph */
+};
+
+#define DEF_HAIRS_DASHES (char *)NULL
+#define DEF_HAIRS_FOREGROUND RGB_BLACK
+#define DEF_HAIRS_LINE_WIDTH "0"
+#define DEF_HAIRS_HIDE "yes"
+#define DEF_HAIRS_POSITION (char *)NULL
+
+extern Blt_CustomOption bltPointOption;
+
+static Blt_ConfigSpec configSpecs[] =
+{
+ {BLT_CONFIG_COLOR, "-color", "color", "Color", DEF_HAIRS_FOREGROUND,
+ Blt_Offset(Crosshairs, colorPtr), 0},
+ {BLT_CONFIG_DASHES, "-dashes", "dashes", "Dashes", DEF_HAIRS_DASHES,
+ Blt_Offset(Crosshairs, dashes), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-hide", "hide", "Hide", DEF_HAIRS_HIDE,
+ Blt_Offset(Crosshairs, hidden), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "Linewidth",
+ DEF_HAIRS_LINE_WIDTH, Blt_Offset(Crosshairs, lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-position", "position", "Position",
+ DEF_HAIRS_POSITION, Blt_Offset(Crosshairs, hotSpot), 0, &bltPointOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TurnOffHairs --
+ *
+ * XOR's the existing line segments (representing the crosshairs),
+ * thereby erasing them. The internal state of the crosshairs is
+ * tracked.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Crosshairs are erased.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+TurnOffHairs(Tk_Window tkwin, Crosshairs *chPtr)
+{
+ if (Tk_IsMapped(tkwin) && (chPtr->visible)) {
+ XDrawSegments(Tk_Display(tkwin), Tk_WindowId(tkwin), chPtr->gc,
+ chPtr->segArr, 2);
+ chPtr->visible = FALSE;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TurnOnHairs --
+ *
+ * Draws (by XORing) new line segments, creating the effect of
+ * crosshairs. The internal state of the crosshairs is tracked.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Crosshairs are displayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+TurnOnHairs(Graph *graphPtr, Crosshairs *chPtr)
+{
+ if (Tk_IsMapped(graphPtr->tkwin) && (!chPtr->visible)) {
+ if (!PointInGraph(graphPtr, chPtr->hotSpot.x, chPtr->hotSpot.y)) {
+ return; /* Coordinates are off the graph */
+ }
+ XDrawSegments(graphPtr->display, Tk_WindowId(graphPtr->tkwin),
+ chPtr->gc, chPtr->segArr, 2);
+ chPtr->visible = TRUE;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureCrosshairs --
+ *
+ * Configures attributes of the crosshairs such as line width,
+ * dashes, and position. The crosshairs are first turned off
+ * before any of the attributes changes.
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Crosshair GC is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ConfigureCrosshairs(Graph *graphPtr)
+{
+ XGCValues gcValues;
+ unsigned long gcMask;
+ GC newGC;
+ unsigned long int pixel;
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ /*
+ * Turn off the crosshairs temporarily. This is in case the new
+ * configuration changes the size, style, or position of the lines.
+ */
+ TurnOffHairs(graphPtr->tkwin, chPtr);
+
+ gcValues.function = GXxor;
+
+ if (graphPtr->plotBg == NULL) {
+ /* The graph's color option may not have been set yet */
+ pixel = WhitePixelOfScreen(Tk_Screen(graphPtr->tkwin));
+ } else {
+ pixel = Blt_BackgroundBorderColor(graphPtr->plotBg)->pixel;
+ }
+ gcValues.background = pixel;
+ gcValues.foreground = (pixel ^ chPtr->colorPtr->pixel);
+
+ gcValues.line_width = LineWidth(chPtr->lineWidth);
+ gcMask = (GCForeground | GCBackground | GCFunction | GCLineWidth);
+ if (LineIsDashed(chPtr->dashes)) {
+ gcValues.line_style = LineOnOffDash;
+ gcMask |= GCLineStyle;
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(chPtr->dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &chPtr->dashes);
+ }
+ if (chPtr->gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, chPtr->gc);
+ }
+ chPtr->gc = newGC;
+
+ /*
+ * Are the new coordinates on the graph?
+ */
+ chPtr->segArr[0].x2 = chPtr->segArr[0].x1 = chPtr->hotSpot.x;
+ chPtr->segArr[0].y1 = graphPtr->bottom;
+ chPtr->segArr[0].y2 = graphPtr->top;
+ chPtr->segArr[1].y2 = chPtr->segArr[1].y1 = chPtr->hotSpot.y;
+ chPtr->segArr[1].x1 = graphPtr->left;
+ chPtr->segArr[1].x2 = graphPtr->right;
+
+ if (!chPtr->hidden) {
+ TurnOnHairs(graphPtr, chPtr);
+ }
+}
+
+void
+Blt_EnableCrosshairs(Graph *graphPtr)
+{
+ if (!graphPtr->crosshairs->hidden) {
+ TurnOnHairs(graphPtr, graphPtr->crosshairs);
+ }
+}
+
+void
+Blt_DisableCrosshairs(Graph *graphPtr)
+{
+ if (!graphPtr->crosshairs->hidden) {
+ TurnOffHairs(graphPtr->tkwin, graphPtr->crosshairs);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UpdateCrosshairs --
+ *
+ * Update the length of the hairs (not the hot spot).
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_UpdateCrosshairs(Graph *graphPtr)
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ chPtr->segArr[0].y1 = graphPtr->bottom;
+ chPtr->segArr[0].y2 = graphPtr->top;
+ chPtr->segArr[1].x1 = graphPtr->left;
+ chPtr->segArr[1].x2 = graphPtr->right;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DestroyCrosshairs --
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Crosshair GC is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DestroyCrosshairs(Graph *graphPtr)
+{
+ if (graphPtr->crosshairs != NULL) {
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ Blt_FreeOptions(configSpecs, (char *)chPtr, graphPtr->display, 0);
+ if (chPtr->gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, chPtr->gc);
+ }
+ free(chPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CreateCrosshairs --
+ *
+ * Creates and initializes a new crosshair structure.
+ *
+ * Results:
+ * Returns TCL_ERROR if the crosshair structure can't be created,
+ * otherwise TCL_OK.
+ *
+ * Side Effects:
+ * Crosshair GC is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_CreateCrosshairs(Graph *graphPtr)
+{
+ Crosshairs *chPtr;
+
+ chPtr = calloc(1, sizeof(Crosshairs));
+ chPtr->hidden = TRUE;
+ chPtr->hotSpot.x = chPtr->hotSpot.y = -1;
+ graphPtr->crosshairs = chPtr;
+
+ if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
+ "crosshairs", "Crosshairs", configSpecs, 0, (Tcl_Obj **)NULL,
+ (char *)chPtr, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ * Queries configuration attributes of the crosshairs such as
+ * line width, dashes, and position.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+CgetOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv)
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)chPtr, objv[3], 0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Queries or resets configuration attributes of the crosshairs
+ * such as line width, dashes, and position.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Crosshairs are reset.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ if (objc == 3) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)chPtr, (Tcl_Obj *)NULL, 0);
+ } else if (objc == 4) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)chPtr, objv[3], 0);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc - 3, objv + 3, (char *)chPtr, BLT_CONFIG_OBJV_ONLY) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_ConfigureCrosshairs(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OnOp --
+ *
+ * Maps the crosshairs.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Crosshairs are reset if necessary.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+OnOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv) /* Not used. */
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ if (chPtr->hidden) {
+ TurnOnHairs(graphPtr, chPtr);
+ chPtr->hidden = FALSE;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OffOp --
+ *
+ * Unmaps the crosshairs.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Crosshairs are reset if necessary.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+OffOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv) /* Not used. */
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ if (!chPtr->hidden) {
+ TurnOffHairs(graphPtr->tkwin, chPtr);
+ chPtr->hidden = TRUE;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ToggleOp --
+ *
+ * Toggles the state of the crosshairs.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Crosshairs are reset.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ToggleOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp, /* Not used. */
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv) /* Not used. */
+{
+ Crosshairs *chPtr = graphPtr->crosshairs;
+
+ chPtr->hidden = (chPtr->hidden == 0);
+ if (chPtr->hidden) {
+ TurnOffHairs(graphPtr->tkwin, chPtr);
+ } else {
+ TurnOnHairs(graphPtr, chPtr);
+ }
+ return TCL_OK;
+}
+
+
+static Blt_OpSpec xhairOps[] =
+{
+ {"cget", 2, CgetOp, 4, 4, "option",},
+ {"configure", 2, ConfigureOp, 3, 0, "?options...?",},
+ {"off", 2, OffOp, 3, 3, "",},
+ {"on", 2, OnOp, 3, 3, "",},
+ {"toggle", 1, ToggleOp, 3, 3, "",},
+};
+static int nXhairOps = sizeof(xhairOps) / sizeof(Blt_OpSpec);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CrosshairsOp --
+ *
+ * User routine to configure crosshair simulation. Crosshairs
+ * are simulated by drawing line segments parallel to both axes
+ * using the XOR drawing function. The allows the lines to be
+ * erased (by drawing them again) without redrawing the entire
+ * graph. Care must be taken to erase crosshairs before redrawing
+ * the graph and redraw them after the graph is redraw.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ * Crosshairs may be drawn in the plotting area.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_CrosshairsOp(
+ Graph *graphPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphCrosshairProc *proc;
+
+ proc = Blt_GetOpFromObj(interp, nXhairOps, xhairOps, BLT_OP_ARG2,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ return (*proc) (graphPtr, interp, objc, objv);
+}
diff --git a/tlt3.0/bltGrLegd.c b/tlt3.0/bltGrLegd.c
new file mode 100644
index 0000000..c0f5b08
--- /dev/null
+++ b/tlt3.0/bltGrLegd.c
@@ -0,0 +1,2838 @@
+
+/*
+ * bltGrLegd.c --
+ *
+ * This module implements the legend for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include "bltInt.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltGrElem.h"
+
+/*
+ * Selection related flags:
+ *
+ * SELECT_EXPORT Export the selection to X11.
+ *
+ * SELECT_PENDING A "selection" command idle task is pending.
+ *
+ * SELECT_CLEAR Clear selection flag of entry.
+ *
+ * SELECT_SET Set selection flag of entry.
+ *
+ * SELECT_TOGGLE Toggle selection flag of entry.
+ *
+ * SELECT_BLTMASK Mask of selection set/clear/toggle flags.
+ *
+ * SELECT_SORTED Indicates if the entries in the selection
+ * should be sorted or displayed in the order
+ * they were selected.
+ *
+ */
+
+#define SELECT_CLEAR (1<<16)
+#define SELECT_EXPORT (1<<17)
+#define SELECT_PENDING (1<<18)
+#define SELECT_SET (1<<19)
+#define SELECT_TOGGLE (SELECT_SET | SELECT_CLEAR)
+#define SELECT_BLTMASK (SELECT_SET | SELECT_CLEAR)
+#define SELECT_SORTED (1<<20)
+
+#define RAISED (1<<21)
+
+#define SELECT_MODE_SINGLE (1<<0)
+#define SELECT_MODE_MULTIPLE (1<<1)
+
+typedef int (GraphLegendProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+/*
+ * Legend --
+ *
+ * Contains information specific to how the legend will be displayed.
+ */
+struct _Legend {
+ unsigned int flags;
+ ClassId classId; /* Type: Element or Marker. */
+
+ int nEntries; /* Number of element entries in
+ * table. */
+ short int nColumns, nRows; /* Number of columns and rows in
+ * legend */
+ short int width, height; /* Dimensions of the legend */
+ short int entryWidth, entryHeight;
+
+ int site;
+ short int xReq, yReq; /* User-requested site of legend, not
+ * the final actual position. Used in
+ * conjunction with the anchor below
+ * to determine location of the
+ * legend. */
+
+ Tk_Anchor anchor; /* Anchor of legend. Used to interpret
+ * the positioning point of the legend
+ * in the graph*/
+
+ int x, y; /* Computed origin of legend. */
+
+ Graph *graphPtr;
+ Tcl_Command cmdToken; /* Token for graph's widget command. */
+ int reqColumns, reqRows;
+
+ Blt_Pad ixPad, iyPad; /* # of pixels interior padding around
+ * legend entries */
+ Blt_Pad xPad, yPad; /* # of pixels padding to exterior of
+ * legend */
+ Tk_Window tkwin; /* If non-NULL, external window to draw
+ * legend. */
+ TextStyle style;
+
+ int maxSymSize; /* Size of largest symbol to be
+ * displayed. Used to calculate size
+ * of legend */
+ XColor *fgColor;
+ Blt_Background activeBg; /* Active legend entry background
+ * color. */
+ XColor *activeFgColor;
+ int activeRelief; /* 3-D effect on active entry. */
+ int entryBW; /* Border width around each entry in
+ * legend. */
+ Blt_Background normalBg; /* 3-D effect of legend. */
+ int borderWidth; /* Width of legend 3-D border */
+ int relief; /* 3-d effect of border around the
+ * legend: TK_RELIEF_RAISED etc. */
+
+ Blt_BindTable bindTable;
+
+ int selRelief;
+ int selBW;
+
+ XColor *selInFocusFgColor; /* Text color of a selected entry. */
+ XColor *selOutFocusFgColor;
+
+ Blt_Background selInFocusBg;
+ Blt_Background selOutFocusBg;
+
+ XColor *focusColor;
+ Blt_Dashes focusDashes; /* Dash on-off value. */
+ GC focusGC; /* Graphics context for the active
+ * label. */
+
+ const char *takeFocus;
+ int focus; /* Position of the focus entry. */
+
+ int cursorX, cursorY; /* Position of the insertion cursor in
+ * the textbox window. */
+ short int cursorWidth; /* Size of the insertion cursor
+ * symbol. */
+ short int cursorHeight;
+ Element *focusPtr; /* Element that currently has the
+ * focus. If NULL, no legend entry has
+ * the focus. */
+ Element *selAnchorPtr; /* Fixed end of selection. Used to
+ * extend the selection while
+ * maintaining the other end of the
+ * selection. */
+ Element *selMarkPtr;
+ Element *selFirstPtr; /* First element selected in current
+ * pick. */
+ Element *selLastPtr; /* Last element selected in current
+ * pick. */
+ int exportSelection;
+ int active;
+ int cursorOn; /* Indicates if the cursor is
+ * displayed. */
+ int onTime, offTime; /* Time in milliseconds to wait before
+ * changing the cursor from off-to-on
+ * and on-to-off. Setting offTime to 0
+ * makes the * cursor steady. */
+ Tcl_TimerToken timerToken; /* Handle for a timer event called
+ * periodically to blink the cursor. */
+ const char *selectCmd; /* TCL script that's invoked whenever
+ * the selection changes. */
+ int selectMode; /* Mode of selection: single or
+ * multiple. */
+ Blt_HashTable selectTable; /* Table of selected elements. Used to
+ * quickly determine whether an element
+ * is selected. */
+ Blt_Chain selected; /* List of selected elements. */
+
+ const char *title;
+ unsigned int titleWidth, titleHeight;
+ TextStyle titleStyle; /* Legend title attributes */
+};
+
+#define padLeft xPad.side1
+#define padRight xPad.side2
+#define padTop yPad.side1
+#define padBottom yPad.side2
+#define PADDING(x) ((x).side1 + (x).side2)
+#define LABEL_PAD 2
+
+#define DEF_LEGEND_ACTIVEBACKGROUND RGB_SKYBLUE4
+#define DEF_LEGEND_ACTIVEBORDERWIDTH "2"
+#define DEF_LEGEND_ACTIVEFOREGROUND RGB_WHITE
+#define DEF_LEGEND_ACTIVERELIEF "flat"
+#define DEF_LEGEND_ANCHOR "n"
+#define DEF_LEGEND_BACKGROUND (char *)NULL
+#define DEF_LEGEND_BORDERWIDTH STD_BORDERWIDTH
+#define DEF_LEGEND_COLUMNS "0"
+#define DEF_LEGEND_EXPORTSELECTION "no"
+#define DEF_LEGEND_FONT "{Sans Serif} 8"
+#define DEF_LEGEND_FOREGROUND STD_NORMAL_FOREGROUND
+#define DEF_LEGEND_HIDE "no"
+#define DEF_LEGEND_IPADX "1"
+#define DEF_LEGEND_IPADY "1"
+#define DEF_LEGEND_PADX "1"
+#define DEF_LEGEND_PADY "1"
+#define DEF_LEGEND_POSITION "rightmargin"
+#define DEF_LEGEND_RAISED "no"
+#define DEF_LEGEND_RELIEF "flat"
+#define DEF_LEGEND_ROWS "0"
+#define DEF_LEGEND_SELECTBACKGROUND RGB_SKYBLUE4
+#define DEF_LEGEND_SELECT_BG_MONO STD_SELECT_BG_MONO
+#define DEF_LEGEND_SELECTBORDERWIDTH "1"
+#define DEF_LEGEND_SELECTMODE "multiple"
+#define DEF_LEGEND_SELECT_FG_MONO STD_SELECT_FG_MONO
+#define DEF_LEGEND_SELECTFOREGROUND RGB_WHITE /*STD_SELECT_FOREGROUND*/
+#define DEF_LEGEND_SELECTRELIEF "flat"
+#define DEF_LEGEND_FOCUSDASHES "dot"
+#define DEF_LEGEND_FOCUSEDIT "no"
+#define DEF_LEGEND_FOCUSFOREGROUND STD_ACTIVE_FOREGROUND
+#define DEF_LEGEND_FOCUS_FG_MONO STD_ACTIVE_FG_MONO
+#define DEF_LEGEND_TAKEFOCUS "1"
+#define DEF_LEGEND_TITLE (char *)NULL
+#define DEF_LEGEND_TITLECOLOR STD_NORMAL_FOREGROUND
+#define DEF_LEGEND_TITLEFONT "{Sans Serif} 8 bold"
+
+static Blt_OptionParseProc ObjToPosition;
+static Blt_OptionPrintProc PositionToObj;
+static Blt_CustomOption legendPositionOption =
+{
+ ObjToPosition, PositionToObj, NULL, (ClientData)0
+};
+
+static Blt_OptionParseProc ObjToSelectmode;
+static Blt_OptionPrintProc SelectmodeToObj;
+static Blt_CustomOption selectmodeOption = {
+ ObjToSelectmode, SelectmodeToObj, NULL, NULL,
+};
+
+static Blt_ConfigSpec configSpecs[] =
+{
+ {BLT_CONFIG_BACKGROUND, "-activebackground", "activeBackground",
+ "ActiveBackground", DEF_LEGEND_ACTIVEBACKGROUND,
+ Blt_Offset(Legend, activeBg), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-activeborderwidth", "activeBorderWidth",
+ "BorderWidth", DEF_LEGEND_BORDERWIDTH,
+ Blt_Offset(Legend, entryBW), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_COLOR, "-activeforeground", "activeForeground",
+ "ActiveForeground", DEF_LEGEND_ACTIVEFOREGROUND,
+ Blt_Offset(Legend, activeFgColor), 0},
+ {BLT_CONFIG_RELIEF, "-activerelief", "activeRelief", "Relief",
+ DEF_LEGEND_ACTIVERELIEF, Blt_Offset(Legend, activeRelief),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", DEF_LEGEND_ANCHOR,
+ Blt_Offset(Legend, anchor), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_LEGEND_BACKGROUND, Blt_Offset(Legend, normalBg),BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_NNEG, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_LEGEND_BORDERWIDTH, Blt_Offset(Legend, borderWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL, 0,0},
+ {BLT_CONFIG_INT_NNEG, "-columns", "columns", "columns",
+ DEF_LEGEND_COLUMNS, Blt_Offset(Legend, reqColumns),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-exportselection", "exportSelection",
+ "ExportSelection", DEF_LEGEND_EXPORTSELECTION,
+ Blt_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)SELECT_EXPORT},
+ {BLT_CONFIG_DASHES, "-focusdashes", "focusDashes", "FocusDashes",
+ DEF_LEGEND_FOCUSDASHES, Blt_Offset(Legend, focusDashes),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
+ DEF_LEGEND_FOCUSFOREGROUND, Blt_Offset(Legend, focusColor),
+ BLT_CONFIG_COLOR_ONLY},
+ {BLT_CONFIG_COLOR, "-focusforeground", "focusForeground", "FocusForeground",
+ DEF_LEGEND_FOCUS_FG_MONO, Blt_Offset(Legend, focusColor),
+ BLT_CONFIG_MONO_ONLY},
+ {BLT_CONFIG_FONT, "-font", "font", "Font", DEF_LEGEND_FONT,
+ Blt_Offset(Legend, style.font), 0},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_LEGEND_FOREGROUND, Blt_Offset(Legend, fgColor), 0},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_LEGEND_HIDE,
+ Blt_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_PAD, "-ipadx", "iPadX", "Pad", DEF_LEGEND_IPADX,
+ Blt_Offset(Legend, ixPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PAD, "-ipady", "iPadY", "Pad", DEF_LEGEND_IPADY,
+ Blt_Offset(Legend, iyPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BACKGROUND, "-nofocusselectbackground",
+ "noFocusSelectBackground", "NoFocusSelectBackground",
+ DEF_LEGEND_SELECTBACKGROUND, Blt_Offset(Legend, selOutFocusBg), 0},
+ {BLT_CONFIG_COLOR, "-nofocusselectforeground", "noFocusSelectForeground",
+ "NoFocusSelectForeground", DEF_LEGEND_SELECTFOREGROUND,
+ Blt_Offset(Legend, selOutFocusFgColor), 0},
+ {BLT_CONFIG_PAD, "-padx", "padX", "Pad", DEF_LEGEND_PADX,
+ Blt_Offset(Legend, xPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PAD, "-pady", "padY", "Pad", DEF_LEGEND_PADY,
+ Blt_Offset(Legend, yPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-position", "position", "Position",
+ DEF_LEGEND_POSITION, 0, BLT_CONFIG_DONT_SET_DEFAULT,
+ &legendPositionOption},
+ {BLT_CONFIG_BITMASK, "-raised", "raised", "Raised", DEF_LEGEND_RAISED,
+ Blt_Offset(Legend, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)RAISED},
+ {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_LEGEND_RELIEF,
+ Blt_Offset(Legend, relief), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_INT_NNEG, "-rows", "rows", "rows", DEF_LEGEND_ROWS,
+ Blt_Offset(Legend, reqRows),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BACKGROUND, "-selectbackground", "selectBackground",
+ "Background", DEF_LEGEND_SELECTBACKGROUND,
+ Blt_Offset(Legend, selInFocusBg), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-selectborderwidth", "selectBorderWidth",
+ "BorderWidth", DEF_LEGEND_SELECTBORDERWIDTH,
+ Blt_Offset(Legend, selBW), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-selectcommand", "selectCommand", "SelectCommand",
+ (char *)NULL, Blt_Offset(Legend, selectCmd), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
+ DEF_LEGEND_SELECT_FG_MONO, Blt_Offset(Legend, selInFocusFgColor),
+ BLT_CONFIG_MONO_ONLY},
+ {BLT_CONFIG_COLOR, "-selectforeground", "selectForeground", "Foreground",
+ DEF_LEGEND_SELECTFOREGROUND, Blt_Offset(Legend, selInFocusFgColor),
+ BLT_CONFIG_COLOR_ONLY},
+ {BLT_CONFIG_CUSTOM, "-selectmode", "selectMode", "SelectMode",
+ DEF_LEGEND_SELECTMODE, Blt_Offset(Legend, selectMode),
+ BLT_CONFIG_DONT_SET_DEFAULT, &selectmodeOption},
+ {BLT_CONFIG_RELIEF, "-selectrelief", "selectRelief", "Relief",
+ DEF_LEGEND_SELECTRELIEF, Blt_Offset(Legend, selRelief),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_LEGEND_TAKEFOCUS, Blt_Offset(Legend, takeFocus),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-title", "title", "Title", DEF_LEGEND_TITLE,
+ Blt_Offset(Legend, title), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-titlecolor", "titleColor", "Foreground",
+ DEF_LEGEND_TITLECOLOR, Blt_Offset(Legend, titleStyle.color), 0},
+ {BLT_CONFIG_FONT, "-titlefont", "titleFont", "Font",
+ DEF_LEGEND_TITLEFONT, Blt_Offset(Legend, titleStyle.font), 0},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static Tcl_IdleProc DisplayLegend;
+static Blt_BindPickProc PickEntryProc;
+static Tk_EventProc LegendEventProc;
+static Tcl_TimerProc BlinkCursorProc;
+static Tk_LostSelProc LostSelectionProc;
+static Tk_SelectionProc SelectionProc;
+
+extern Tcl_ObjCmdProc Blt_GraphInstCmdProc;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Legend_EventuallyRedraw --
+ *
+ * Tells the Tk dispatcher to call the graph display routine at the next
+ * idle point. This request is made only if the window is displayed and
+ * no other redraw request is pending.
+ *
+ * Results: None.
+ *
+ * Side effects:
+ * The window is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Legend_EventuallyRedraw(Graph *graphPtr)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ if ((legendPtr->tkwin != NULL) && !(legendPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayLegend, legendPtr);
+ legendPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectCmdProc --
+ *
+ * Invoked at the next idle point whenever the current selection changes.
+ * Executes some application-specific code in the -selectcommand option.
+ * This provides a way for applications to handle selection changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TCL code gets executed for some application-specific task.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+SelectCmdProc(ClientData clientData)
+{
+ Legend *legendPtr = clientData;
+
+ Tcl_Preserve(legendPtr);
+ legendPtr->flags &= ~SELECT_PENDING;
+ if (legendPtr->selectCmd != NULL) {
+ Tcl_Interp *interp;
+
+ interp = legendPtr->graphPtr->interp;
+ if (Tcl_GlobalEval(interp, legendPtr->selectCmd) != TCL_OK) {
+ Tcl_BackgroundError(interp);
+ }
+ }
+ Tcl_Release(legendPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * EventuallyInvokeSelectCmd --
+ *
+ * Queues a request to execute the -selectcommand code associated with
+ * the widget at the next idle point. Invoked whenever the selection
+ * changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TCL code gets executed for some application-specific task.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+EventuallyInvokeSelectCmd(Legend *legendPtr)
+{
+ if ((legendPtr->flags & SELECT_PENDING) == 0) {
+ legendPtr->flags |= SELECT_PENDING;
+ Tcl_DoWhenIdle(SelectCmdProc, legendPtr);
+ }
+}
+
+static void
+ClearSelection(Legend *legendPtr)
+{
+ Blt_DeleteHashTable(&legendPtr->selectTable);
+ Blt_InitHashTable(&legendPtr->selectTable, BLT_ONE_WORD_KEYS);
+ Blt_Chain_Reset(legendPtr->selected);
+ Blt_Legend_EventuallyRedraw(legendPtr->graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LostSelectionProc --
+ *
+ * This procedure is called back by Tk when the selection is grabbed away
+ * from a Text widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The existing selection is unhighlighted, and the window is marked as
+ * not containing a selection.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+LostSelectionProc(ClientData clientData)
+{
+ Legend *legendPtr = clientData;
+
+ if (legendPtr->flags & SELECT_EXPORT) {
+ ClearSelection(legendPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LegendEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various events on
+ * graphs.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, the graph is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+LegendEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
+
+ legendPtr = graphPtr->legend;
+ if (eventPtr->type == Expose) {
+ if (eventPtr->xexpose.count == 0) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
+ if (eventPtr->xfocus.detail == NotifyInferior) {
+ return;
+ }
+ if (eventPtr->type == FocusIn) {
+ legendPtr->flags |= FOCUS;
+ } else {
+ legendPtr->flags &= ~FOCUS;
+ }
+ Tcl_DeleteTimerHandler(legendPtr->timerToken);
+ if ((legendPtr->active) && (legendPtr->flags & FOCUS)) {
+ legendPtr->cursorOn = TRUE;
+ if (legendPtr->offTime != 0) {
+ legendPtr->timerToken = Tcl_CreateTimerHandler(
+ legendPtr->onTime, BlinkCursorProc, graphPtr);
+ }
+ } else {
+ legendPtr->cursorOn = FALSE;
+ legendPtr->timerToken = (Tcl_TimerToken)NULL;
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ } else if (eventPtr->type == DestroyNotify) {
+ Graph *graphPtr = legendPtr->graphPtr;
+
+ if (legendPtr->site == LEGEND_WINDOW) {
+ if (legendPtr->cmdToken != NULL) {
+ Tcl_DeleteCommandFromToken(graphPtr->interp,
+ legendPtr->cmdToken);
+ legendPtr->cmdToken = NULL;
+ }
+ legendPtr->tkwin = graphPtr->tkwin;
+ }
+ if (legendPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayLegend, legendPtr);
+ legendPtr->flags &= ~REDRAW_PENDING;
+ }
+ legendPtr->site = LEGEND_RIGHT;
+ legendPtr->flags |= HIDE;
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_MoveBindingTable(legendPtr->bindTable, graphPtr->tkwin);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ } else if (eventPtr->type == ConfigureNotify) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+}
+
+static int
+CreateLegendWindow(Tcl_Interp *interp, Legend *legendPtr, const char *pathName)
+{
+ Graph *graphPtr;
+ Tk_Window tkwin;
+
+ graphPtr = legendPtr->graphPtr;
+ tkwin = Tk_CreateWindowFromPath(interp, graphPtr->tkwin, pathName, NULL);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ Blt_SetWindowInstanceData(tkwin, legendPtr);
+ Tk_CreateEventHandler(tkwin, ExposureMask | StructureNotifyMask,
+ LegendEventProc, graphPtr);
+ /* Move the legend's binding table to the new window. */
+ Blt_MoveBindingTable(legendPtr->bindTable, tkwin);
+ if (legendPtr->tkwin != graphPtr->tkwin) {
+ Tk_DestroyWindow(legendPtr->tkwin);
+ }
+ /* Create a command by the same name as the legend window so that Legend
+ * bindings can use %W interchangably. */
+ legendPtr->cmdToken = Tcl_CreateObjCommand(interp, pathName,
+ Blt_GraphInstCmdProc, graphPtr, NULL);
+ legendPtr->tkwin = tkwin;
+ legendPtr->site = LEGEND_WINDOW;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPosition --
+ *
+ * Convert the string representation of a legend XY position into window
+ * coordinates. The form of the string must be "@x,y" or none.
+ *
+ * Results:
+ * The return value is a standard TCL result. The symbol type is written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPosition(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* New legend position string */
+ char *widgRec, /* Widget record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Graph *graphPtr;
+ Legend *legendPtr = (Legend *)widgRec;
+ char c;
+ int length;
+ const char *string;
+
+ graphPtr = legendPtr->graphPtr;
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if (c == '\0') {
+ legendPtr->site = LEGEND_RIGHT;
+ } else if ((c == 'l') && (strncmp(string, "leftmargin", length) == 0)) {
+ legendPtr->site = LEGEND_LEFT;
+ } else if ((c == 'r') && (strncmp(string, "rightmargin", length) == 0)) {
+ legendPtr->site = LEGEND_RIGHT;
+ } else if ((c == 't') && (strncmp(string, "topmargin", length) == 0)) {
+ legendPtr->site = LEGEND_TOP;
+ } else if ((c == 'b') && (strncmp(string, "bottommargin", length) == 0)) {
+ legendPtr->site = LEGEND_BOTTOM;
+ } else if ((c == 'p') && (strncmp(string, "plotarea", length) == 0)) {
+ legendPtr->site = LEGEND_PLOT;
+ } else if (c == '@') {
+ char *comma;
+ long x, y;
+ int result;
+
+ comma = strchr(string + 1, ',');
+ if (comma == NULL) {
+ Tcl_AppendResult(interp, "bad screen position \"", string,
+ "\": should be @x,y", (char *)NULL);
+ return TCL_ERROR;
+ }
+ x = y = 0;
+ *comma = '\0';
+ result = ((Tcl_ExprLong(interp, string + 1, &x) == TCL_OK) &&
+ (Tcl_ExprLong(interp, comma + 1, &y) == TCL_OK));
+ *comma = ',';
+ if (!result) {
+ return TCL_ERROR;
+ }
+ legendPtr->xReq = x;
+ legendPtr->yReq = y;
+ legendPtr->site = LEGEND_XY;
+ } else if (c == '.') {
+ if (CreateLegendWindow(interp, legendPtr, string) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ } else {
+ Tcl_AppendResult(interp, "bad position \"", string, "\": should be \
+\"leftmargin\", \"rightmargin\", \"topmargin\", \"bottommargin\", \
+\"plotarea\", windowName or @x,y", (char *)NULL);
+ return TCL_ERROR;
+ }
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PositionToObj --
+ *
+ * Convert the window coordinates into a string.
+ *
+ * Results:
+ * The string representing the coordinate position is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PositionToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Legend *legendPtr = (Legend *)widgRec;
+ Tcl_Obj *objPtr;
+
+ switch (legendPtr->site) {
+ case LEGEND_LEFT:
+ objPtr = Tcl_NewStringObj("leftmargin", -1);
+ break;
+
+ case LEGEND_RIGHT:
+ objPtr = Tcl_NewStringObj("rightmargin", -1);
+ break;
+
+ case LEGEND_TOP:
+ objPtr = Tcl_NewStringObj("topmargin", -1);
+ break;
+
+ case LEGEND_BOTTOM:
+ objPtr = Tcl_NewStringObj("bottommargin", -1);
+ break;
+
+ case LEGEND_PLOT:
+ objPtr = Tcl_NewStringObj("plotarea", -1);
+ break;
+
+ case LEGEND_WINDOW:
+ objPtr = Tcl_NewStringObj(Tk_PathName(legendPtr->tkwin), -1);
+ break;
+
+ case LEGEND_XY:
+ {
+ char string[200];
+
+ sprintf_s(string, 200, "@%d,%d", legendPtr->xReq, legendPtr->yReq);
+ objPtr = Tcl_NewStringObj(string, -1);
+ }
+ default:
+ objPtr = Tcl_NewStringObj("unknown legend position", -1);
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToSelectmode --
+ *
+ * Convert the string reprsenting a select mode, to its numeric form.
+ *
+ * Results:
+ * If the string is successfully converted, TCL_OK is returned.
+ * Otherwise, TCL_ERROR is returned and an error message is left
+ * in interpreter's result field.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToSelectmode(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* Tcl_Obj representing the new value. */
+ char *widgRec,
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ char *string;
+ char c;
+ int *modePtr = (int *)(widgRec + offset);
+
+ string = Tcl_GetString(objPtr);
+ c = string[0];
+ if ((c == 's') && (strcmp(string, "single") == 0)) {
+ *modePtr = SELECT_MODE_SINGLE;
+ } else if ((c == 'm') && (strcmp(string, "multiple") == 0)) {
+ *modePtr = SELECT_MODE_MULTIPLE;
+ } else if ((c == 'a') && (strcmp(string, "active") == 0)) {
+ *modePtr = SELECT_MODE_SINGLE;
+ } else {
+ Tcl_AppendResult(interp, "bad select mode \"", string,
+ "\": should be \"single\" or \"multiple\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectmodeToObj --
+ *
+ * Results:
+ * The string representation of the select mode is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+SelectmodeToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec,
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ int mode = *(int *)(widgRec + offset);
+
+ switch (mode) {
+ case SELECT_MODE_SINGLE:
+ return Tcl_NewStringObj("single", -1);
+ case SELECT_MODE_MULTIPLE:
+ return Tcl_NewStringObj("multiple", -1);
+ default:
+ return Tcl_NewStringObj("unknown scroll mode", -1);
+ }
+}
+
+
+static void
+SetLegendOrigin(Legend *legendPtr)
+{
+ Graph *graphPtr;
+ int x, y, w, h;
+
+ graphPtr = legendPtr->graphPtr;
+ x = y = w = h = 0; /* Suppress compiler warning. */
+ switch (legendPtr->site) {
+ case LEGEND_RIGHT:
+ w = graphPtr->rightMargin.width - graphPtr->rightMargin.axesOffset;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->right + graphPtr->rightMargin.axesOffset;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_LEFT:
+ w = graphPtr->leftMargin.width - graphPtr->leftMargin.axesOffset;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->inset;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_TOP:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->topMargin.height - graphPtr->topMargin.axesOffset;
+ if (graphPtr->title != NULL) {
+ h -= graphPtr->titleHeight;
+ }
+ x = graphPtr->left;
+ y = graphPtr->inset;
+ if (graphPtr->title != NULL) {
+ y += graphPtr->titleHeight;
+ }
+ break;
+
+ case LEGEND_BOTTOM:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->bottomMargin.height - graphPtr->bottomMargin.axesOffset;
+ x = graphPtr->left;
+ y = graphPtr->bottom + graphPtr->bottomMargin.axesOffset;
+ break;
+
+ case LEGEND_PLOT:
+ w = graphPtr->right - graphPtr->left;
+ h = graphPtr->bottom - graphPtr->top;
+ x = graphPtr->left;
+ y = graphPtr->top;
+ break;
+
+ case LEGEND_XY:
+ w = legendPtr->width;
+ h = legendPtr->height;
+ x = legendPtr->xReq;
+ y = legendPtr->yReq;
+ if (x < 0) {
+ x += graphPtr->width;
+ }
+ if (y < 0) {
+ y += graphPtr->height;
+ }
+ break;
+
+ case LEGEND_WINDOW:
+ legendPtr->anchor = TK_ANCHOR_NW;
+ legendPtr->x = legendPtr->y = 0;
+ return;
+ }
+
+ switch (legendPtr->anchor) {
+ case TK_ANCHOR_NW: /* Upper left corner */
+ break;
+ case TK_ANCHOR_W: /* Left center */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ break;
+ case TK_ANCHOR_SW: /* Lower left corner */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ case TK_ANCHOR_N: /* Top center */
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ break;
+ case TK_ANCHOR_CENTER: /* Center */
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ break;
+ case TK_ANCHOR_S: /* Bottom center */
+ if (w > legendPtr->width) {
+ x += (w - legendPtr->width) / 2;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ case TK_ANCHOR_NE: /* Upper right corner */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ break;
+ case TK_ANCHOR_E: /* Right center */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height) / 2;
+ }
+ break;
+ case TK_ANCHOR_SE: /* Lower right corner */
+ if (w > legendPtr->width) {
+ x += w - legendPtr->width;
+ }
+ if (h > legendPtr->height) {
+ y += (h - legendPtr->height);
+ }
+ break;
+ }
+ legendPtr->x = x + legendPtr->padLeft;
+ legendPtr->y = y + legendPtr->padTop;
+}
+
+static int
+EntryIsSelected(Legend *legendPtr, Element *elemPtr)
+{
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ return (hPtr != NULL);
+}
+
+static void
+SelectElement(Legend *legendPtr, Element *elemPtr)
+{
+ int isNew;
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_CreateHashEntry(&legendPtr->selectTable, (char *)elemPtr,&isNew);
+ if (isNew) {
+ Blt_ChainLink link;
+
+ link = Blt_Chain_Append(legendPtr->selected, elemPtr);
+ Blt_SetHashValue(hPtr, link);
+ }
+}
+
+static void
+DeselectElement(Legend *legendPtr, Element *elemPtr)
+{
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ if (hPtr != NULL) {
+ Blt_ChainLink link;
+
+ link = Blt_GetHashValue(hPtr);
+ Blt_Chain_DeleteLink(legendPtr->selected, link);
+ Blt_DeleteHashEntry(&legendPtr->selectTable, hPtr);
+ }
+}
+
+static void
+SelectEntry(Legend *legendPtr, Element *elemPtr)
+{
+ Blt_HashEntry *hPtr;
+
+ switch (legendPtr->flags & SELECT_BLTMASK) {
+ case SELECT_CLEAR:
+ DeselectElement(legendPtr, elemPtr);
+ break;
+
+ case SELECT_SET:
+ SelectElement(legendPtr, elemPtr);
+ break;
+
+ case SELECT_TOGGLE:
+ hPtr = Blt_FindHashEntry(&legendPtr->selectTable, (char *)elemPtr);
+ if (hPtr != NULL) {
+ DeselectElement(legendPtr, elemPtr);
+ } else {
+ SelectElement(legendPtr, elemPtr);
+ }
+ break;
+ }
+}
+
+/*ARGSUSED*/
+static ClientData
+PickEntryProc(ClientData clientData, int x, int y, ClientData *contextPtr)
+{
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
+ int w, h;
+
+ legendPtr = graphPtr->legend;
+ w = legendPtr->width;
+ h = legendPtr->height;
+
+ if (legendPtr->titleHeight > 0) {
+ y -= legendPtr->titleHeight + legendPtr->yPad.side1;
+ }
+ x -= legendPtr->x + legendPtr->borderWidth;
+ y -= legendPtr->y + legendPtr->borderWidth;
+ w -= 2 * legendPtr->borderWidth + PADDING(legendPtr->xPad);
+ h -= 2 * legendPtr->borderWidth + PADDING(legendPtr->yPad);
+
+ if ((x >= 0) && (x < w) && (y >= 0) && (y < h)) {
+ int row, column;
+ int n;
+
+ /*
+ * It's in the bounding box, so compute the index.
+ */
+ row = y / legendPtr->entryHeight;
+ column = x / legendPtr->entryWidth;
+ n = (column * legendPtr->nRows) + row;
+ if (n < legendPtr->nEntries) {
+ Blt_ChainLink link;
+ int count;
+
+ /* Legend entries are stored in bottom-to-top. */
+ count = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ if (count == n) {
+ return elemPtr;
+ }
+ count++;
+ }
+ }
+ if (link != NULL) {
+ return Blt_Chain_GetValue(link);
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_MapLegend --
+ *
+ * Calculates the dimensions (width and height) needed for the legend.
+ * Also determines the number of rows and columns necessary to list all
+ * the valid element labels.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The following fields of the legend are calculated and set.
+ *
+ * nEntries - number of valid labels of elements in the
+ * display list.
+ * nRows - number of rows of entries
+ * nColumns - number of columns of entries
+ * entryHeight - height of each entry
+ * entryWidth - width of each entry
+ * height - width of legend (includes borders and padding)
+ * width - height of legend (includes borders and padding)
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_MapLegend(
+ Graph *graphPtr,
+ int plotWidth, /* Maximum width available in window
+ * to draw the legend. Will calculate
+ * # of columns from this. */
+ int plotHeight) /* Maximum height available in window
+ * to draw the legend. Will calculate
+ * # of rows from this. */
+{
+ Legend *legendPtr = graphPtr->legend;
+ Blt_ChainLink link;
+ int nRows, nColumns, nEntries;
+ int lw, lh;
+ int maxWidth, maxHeight;
+ int symbolWidth;
+ Blt_FontMetrics fontMetrics;
+
+ /* Initialize legend values to default (no legend displayed) */
+ legendPtr->entryWidth = legendPtr->entryHeight = 0;
+ legendPtr->nRows = legendPtr->nColumns = legendPtr->nEntries = 0;
+ legendPtr->height = legendPtr->width = 0;
+
+ if (legendPtr->site == LEGEND_WINDOW) {
+ if (Tk_Width(legendPtr->tkwin) > 1) {
+ plotWidth = Tk_Width(legendPtr->tkwin);
+ }
+ if (Tk_Height(legendPtr->tkwin) > 1) {
+ plotHeight = Tk_Height(legendPtr->tkwin);
+ }
+ }
+ Blt_Ts_GetExtents(&legendPtr->titleStyle, legendPtr->title,
+ &legendPtr->titleWidth, &legendPtr->titleHeight);
+ /*
+ * Count the number of legend entries and determine the widest and tallest
+ * label. The number of entries would normally be the number of elements,
+ * but elements can have no legend entry (-label "").
+ */
+ nEntries = 0;
+ maxWidth = maxHeight = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ unsigned int w, h;
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Element has no legend entry. */
+ }
+ Blt_Ts_GetExtents(&legendPtr->style, elemPtr->label, &w, &h);
+ if (maxWidth < w) {
+ maxWidth = w;
+ }
+ if (maxHeight < h) {
+ maxHeight = h;
+ }
+ nEntries++;
+ }
+ if (nEntries == 0) {
+ return; /* No visible legend entries. */
+ }
+
+
+ Blt_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+ symbolWidth = 2 * fontMetrics.ascent;
+
+ maxWidth += 2 * legendPtr->entryBW + PADDING(legendPtr->ixPad) +
+ + symbolWidth + 3 * LABEL_PAD;
+
+ maxHeight += 2 * legendPtr->entryBW + PADDING(legendPtr->iyPad);
+
+ maxWidth |= 0x01;
+ maxHeight |= 0x01;
+
+ lw = plotWidth - 2 * legendPtr->borderWidth - PADDING(legendPtr->xPad);
+ lh = plotHeight - 2 * legendPtr->borderWidth - PADDING(legendPtr->yPad);
+
+ /*
+ * The number of rows and columns is computed as one of the following:
+ *
+ * both options set User defined.
+ * -rows Compute columns from rows.
+ * -columns Compute rows from columns.
+ * neither set Compute rows and columns from
+ * size of plot.
+ */
+ if (legendPtr->reqRows > 0) {
+ nRows = MIN(legendPtr->reqRows, nEntries);
+ if (legendPtr->reqColumns > 0) {
+ nColumns = MIN(legendPtr->reqColumns, nEntries);
+ } else {
+ nColumns = ((nEntries - 1) / nRows) + 1; /* Only -rows. */
+ }
+ } else if (legendPtr->reqColumns > 0) { /* Only -columns. */
+ nColumns = MIN(legendPtr->reqColumns, nEntries);
+ nRows = ((nEntries - 1) / nColumns) + 1;
+ } else {
+ /* Compute # of rows and columns from the legend size. */
+ nRows = lh / maxHeight;
+ nColumns = lw / maxWidth;
+ if (nRows < 1) {
+ nRows = nEntries;
+ }
+ if (nColumns < 1) {
+ nColumns = nEntries;
+ }
+ if (nRows > nEntries) {
+ nRows = nEntries;
+ }
+ switch (legendPtr->site) {
+ case LEGEND_TOP:
+ case LEGEND_BOTTOM:
+ nRows = ((nEntries - 1) / nColumns) + 1;
+ break;
+ case LEGEND_LEFT:
+ case LEGEND_RIGHT:
+ default:
+ nColumns = ((nEntries - 1) / nRows) + 1;
+ break;
+ }
+ }
+ if (nColumns < 1) {
+ nColumns = 1;
+ }
+ if (nRows < 1) {
+ nRows = 1;
+ }
+
+ lh = (nRows * maxHeight);
+ if (legendPtr->titleHeight > 0) {
+ lh += legendPtr->titleHeight + legendPtr->yPad.side1;
+ }
+ lw = nColumns * maxWidth;
+ if (lw < legendPtr->titleWidth) {
+ lw = legendPtr->titleWidth;
+ }
+ legendPtr->width = lw + 2 * legendPtr->borderWidth +
+ PADDING(legendPtr->xPad);
+ legendPtr->height = lh + 2 * legendPtr->borderWidth +
+ PADDING(legendPtr->yPad);
+ legendPtr->nRows = nRows;
+ legendPtr->nColumns = nColumns;
+ legendPtr->nEntries = nEntries;
+ legendPtr->entryHeight = maxHeight;
+ legendPtr->entryWidth = maxWidth;
+
+ {
+ int row, col, count;
+
+ row = col = count = 0;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ count++;
+ elemPtr->row = row;
+ elemPtr->col = col;
+ row++;
+ if ((count % nRows) == 0) {
+ col++;
+ row = 0;
+ }
+ }
+ }
+ if ((legendPtr->site == LEGEND_WINDOW) &&
+ ((Tk_ReqWidth(legendPtr->tkwin) != legendPtr->width) ||
+ (Tk_ReqHeight(legendPtr->tkwin) != legendPtr->height))) {
+ Tk_GeometryRequest(legendPtr->tkwin,legendPtr->width,legendPtr->height);
+ }
+}
+
+void
+Blt_DrawLegend(Graph *graphPtr, Drawable drawable)
+{
+ Blt_Background bg;
+ Blt_ChainLink link;
+ Blt_FontMetrics fontMetrics;
+ Legend *legendPtr = graphPtr->legend;
+ Pixmap pixmap;
+ Tk_Window tkwin;
+ int count;
+ int symbolSize, xMid, yMid;
+ int x, y, w, h;
+ int xLabel, yStart, xSymbol, ySymbol;
+
+ if ((legendPtr->flags & HIDE) || (legendPtr->nEntries == 0)) {
+ return;
+ }
+
+ SetLegendOrigin(legendPtr);
+ graphPtr = legendPtr->graphPtr;
+ tkwin = legendPtr->tkwin;
+ if (legendPtr->site == LEGEND_WINDOW) {
+ w = Tk_Width(tkwin);
+ h = Tk_Height(tkwin);
+ } else {
+ w = legendPtr->width;
+ h = legendPtr->height;
+ }
+
+ pixmap = Tk_GetPixmap(graphPtr->display, Tk_WindowId(tkwin), w, h,
+ Tk_Depth(tkwin));
+
+ if (legendPtr->normalBg != NULL) {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->normalBg, 0, 0,
+ w, h, 0, TK_RELIEF_FLAT);
+ } else if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ /*
+ * Legend background is transparent and is positioned over the the
+ * plot area. Either copy the part of the background from the backing
+ * store pixmap or (if no backing store exists) just fill it with the
+ * background color of the plot.
+ */
+ if (graphPtr->cache != None) {
+ XCopyArea(graphPtr->display, graphPtr->cache, pixmap,
+ graphPtr->drawGC, legendPtr->x, legendPtr->y, w, h, 0, 0);
+ } else {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->plotBg, 0, 0,
+ w, h, TK_RELIEF_FLAT, 0);
+ }
+ } else {
+ int xOrigin, yOrigin;
+ /*
+ * The legend is located in one of the margins or the external window.
+ */
+ Blt_GetBackgroundOrigin(graphPtr->normalBg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(graphPtr->tkwin, graphPtr->normalBg,
+ xOrigin - legendPtr->x,yOrigin - legendPtr->y);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg, 0, 0,
+ w, h, 0, TK_RELIEF_FLAT);
+ Blt_SetBackgroundOrigin(tkwin, graphPtr->normalBg, xOrigin, yOrigin);
+ }
+ Blt_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+
+ symbolSize = fontMetrics.ascent;
+ xMid = symbolSize + 1 + legendPtr->entryBW;
+ yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
+ xLabel = 2 * symbolSize + legendPtr->entryBW +
+ legendPtr->ixPad.side1 + 2 * LABEL_PAD;
+ ySymbol = yMid + legendPtr->iyPad.side1;
+ xSymbol = xMid + LABEL_PAD;
+
+ x = legendPtr->padLeft + legendPtr->borderWidth;
+ y = legendPtr->padTop + legendPtr->borderWidth;
+ Blt_DrawText(tkwin, pixmap, legendPtr->title, &legendPtr->titleStyle, x, y);
+ if (legendPtr->titleHeight > 0) {
+ y += legendPtr->titleHeight + legendPtr->yPad.side1;
+ }
+ count = 0;
+ yStart = y;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ int isSelected;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Skip this entry */
+ }
+ isSelected = EntryIsSelected(legendPtr, elemPtr);
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ int xOrigin, yOrigin;
+
+ Blt_GetBackgroundOrigin(legendPtr->activeBg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
+ xOrigin - legendPtr->x, yOrigin - legendPtr->y);
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, legendPtr->activeBg,
+ x, y, legendPtr->entryWidth, legendPtr->entryHeight,
+ legendPtr->entryBW, legendPtr->activeRelief);
+ Blt_SetBackgroundOrigin(tkwin, legendPtr->activeBg,
+ xOrigin, yOrigin);
+ } else if (isSelected) {
+ int xOrigin, yOrigin;
+ Blt_Background bg;
+ XColor *fg;
+
+ fg = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusFgColor : legendPtr->selOutFocusFgColor;
+ bg = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusBg : legendPtr->selOutFocusBg;
+ Blt_GetBackgroundOrigin(bg, &xOrigin, &yOrigin);
+ Blt_SetBackgroundOrigin(tkwin, bg, xOrigin - legendPtr->x,
+ yOrigin - legendPtr->y);
+ Blt_Ts_SetForeground(legendPtr->style, fg);
+ Blt_FillBackgroundRectangle(tkwin, pixmap, bg, x, y,
+ legendPtr->entryWidth, legendPtr->entryHeight,
+ legendPtr->selBW, legendPtr->selRelief);
+ Blt_SetBackgroundOrigin(tkwin, bg, xOrigin, yOrigin);
+ } else {
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
+ if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
+ Blt_FillBackgroundRectangle(tkwin, pixmap, graphPtr->normalBg,
+ x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ elemPtr->legendRelief);
+ }
+ }
+ (*elemPtr->procsPtr->drawSymbolProc) (graphPtr, pixmap, elemPtr,
+ x + xSymbol, y + ySymbol, symbolSize);
+ Blt_DrawText(tkwin, pixmap, elemPtr->label, &legendPtr->style,
+ x + xLabel,
+ y + legendPtr->entryBW + legendPtr->iyPad.side1);
+ count++;
+ if (legendPtr->focusPtr == elemPtr) { /* Focus outline */
+ if (isSelected) {
+ XColor *color;
+
+ color = (legendPtr->flags & FOCUS) ?
+ legendPtr->selInFocusFgColor :
+ legendPtr->selOutFocusFgColor;
+ XSetForeground(graphPtr->display, legendPtr->focusGC,
+ color->pixel);
+ }
+ XDrawRectangle(graphPtr->display, pixmap, legendPtr->focusGC,
+ x + 1, y + 1, legendPtr->entryWidth - 3,
+ legendPtr->entryHeight - 3);
+ if (isSelected) {
+ XSetForeground(graphPtr->display, legendPtr->focusGC,
+ legendPtr->focusColor->pixel);
+ }
+ }
+ /* Check when to move to the next column */
+ if ((count % legendPtr->nRows) > 0) {
+ y += legendPtr->entryHeight;
+ } else {
+ x += legendPtr->entryWidth;
+ y = yStart;
+ }
+ }
+ /*
+ * Draw the border and/or background of the legend.
+ */
+ bg = legendPtr->normalBg;
+ if (bg == NULL) {
+ bg = graphPtr->normalBg;
+ }
+ /* Disable crosshairs before redisplaying to the screen */
+ if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ Blt_DisableCrosshairs(graphPtr);
+ }
+ Blt_DrawBackgroundRectangle(tkwin, pixmap, bg, 0, 0, w, h,
+ legendPtr->borderWidth, legendPtr->relief);
+ XCopyArea(graphPtr->display, pixmap, drawable, graphPtr->drawGC, 0, 0, w, h,
+ legendPtr->x, legendPtr->y);
+ if (legendPtr->site & LEGEND_PLOTAREA_MASK) {
+ Blt_EnableCrosshairs(graphPtr);
+ }
+ Tk_FreePixmap(graphPtr->display, pixmap);
+ graphPtr->flags &= ~DRAW_LEGEND;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_LegendToPostScript --
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_LegendToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ Legend *legendPtr = graphPtr->legend;
+ double x, y, yStart;
+ int xLabel, xSymbol, ySymbol;
+ int count;
+ Blt_ChainLink link;
+ int symbolSize, xMid, yMid;
+ int width, height;
+ Blt_FontMetrics fontMetrics;
+
+ if ((legendPtr->flags & HIDE) || (legendPtr->nEntries == 0)) {
+ return;
+ }
+ SetLegendOrigin(legendPtr);
+
+ x = legendPtr->x, y = legendPtr->y;
+ width = legendPtr->width - PADDING(legendPtr->xPad);
+ height = legendPtr->height - PADDING(legendPtr->yPad);
+
+ Blt_Ps_Append(ps, "% Legend\n");
+ graphPtr = legendPtr->graphPtr;
+ if (graphPtr->pageSetup->flags & PS_DECORATIONS) {
+ if (legendPtr->normalBg != NULL) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(legendPtr->normalBg);
+ Blt_Ps_Fill3DRectangle(ps, border, x, y, width, height,
+ legendPtr->borderWidth, legendPtr->relief);
+ } else {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(graphPtr->normalBg);
+ Blt_Ps_Draw3DRectangle(ps, border, x, y, width, height,
+ legendPtr->borderWidth, legendPtr->relief);
+ }
+ } else {
+ Blt_Ps_SetClearBackground(ps);
+ Blt_Ps_XFillRectangle(ps, x, y, width, height);
+ }
+ Blt_GetFontMetrics(legendPtr->style.font, &fontMetrics);
+ symbolSize = fontMetrics.ascent;
+ xMid = symbolSize + 1 + legendPtr->entryBW;
+ yMid = (symbolSize / 2) + 1 + legendPtr->entryBW;
+ xLabel = 2 * symbolSize + legendPtr->entryBW + legendPtr->ixPad.side1 + 5;
+ xSymbol = xMid + legendPtr->ixPad.side1;
+ ySymbol = yMid + legendPtr->iyPad.side1;
+
+ x += legendPtr->borderWidth;
+ y += legendPtr->borderWidth;
+ Blt_Ps_DrawText(ps, legendPtr->title, &legendPtr->titleStyle, x, y);
+ if (legendPtr->titleHeight > 0) {
+ y += legendPtr->titleHeight + legendPtr->yPad.side1;
+ }
+
+ count = 0;
+ yStart = y;
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue; /* Skip this label */
+ }
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(legendPtr->activeBg);
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->activeFgColor);
+ Blt_Ps_Fill3DRectangle(ps, border, x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ legendPtr->activeRelief);
+ } else {
+ Blt_Ts_SetForeground(legendPtr->style, legendPtr->fgColor);
+ if (elemPtr->legendRelief != TK_RELIEF_FLAT) {
+ Tk_3DBorder border;
+
+ border = Blt_BackgroundBorder(graphPtr->normalBg);
+ Blt_Ps_Draw3DRectangle(ps, border, x, y, legendPtr->entryWidth,
+ legendPtr->entryHeight, legendPtr->entryBW,
+ elemPtr->legendRelief);
+ }
+ }
+ (*elemPtr->procsPtr->printSymbolProc) (graphPtr, ps, elemPtr,
+ x + xSymbol, y + ySymbol, symbolSize);
+ Blt_Ps_DrawText(ps, elemPtr->label, &legendPtr->style,
+ x + xLabel, y + legendPtr->entryBW + legendPtr->iyPad.side1);
+ count++;
+ if ((count % legendPtr->nRows) > 0) {
+ y += legendPtr->entryHeight;
+ } else {
+ x += legendPtr->entryWidth;
+ y = yStart;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DisplayLegend --
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DisplayLegend(ClientData clientData)
+{
+ Legend *legendPtr = clientData;
+ Graph *graphPtr;
+
+ legendPtr->flags &= ~REDRAW_PENDING;
+ if (legendPtr->tkwin == NULL) {
+ return; /* Window has been destroyed. */
+ }
+ graphPtr = legendPtr->graphPtr;
+ if (legendPtr->site == LEGEND_WINDOW) {
+ int w, h;
+
+ w = Tk_Width(legendPtr->tkwin);
+ h = Tk_Height(legendPtr->tkwin);
+ if ((w != legendPtr->width) || (h != legendPtr->height)) {
+ Blt_MapLegend(graphPtr, w, h);
+ }
+ }
+ if (Tk_IsMapped(legendPtr->tkwin)) {
+ Blt_DrawLegend(graphPtr, Tk_WindowId(legendPtr->tkwin));
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureLegend --
+ *
+ * Routine to configure the legend.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ConfigureLegend(Graph *graphPtr)
+{
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+ Legend *legendPtr;
+
+ legendPtr = graphPtr->legend;
+ /* GC for active label. Dashed outline. */
+ gcMask = GCForeground | GCLineStyle;
+ gcValues.foreground = legendPtr->focusColor->pixel;
+ gcValues.line_style = (LineIsDashed(legendPtr->focusDashes))
+ ? LineOnOffDash : LineSolid;
+ newGC = Blt_GetPrivateGC(legendPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(legendPtr->focusDashes)) {
+ legendPtr->focusDashes.offset = 2;
+ Blt_SetDashes(graphPtr->display, newGC, &legendPtr->focusDashes);
+ }
+ if (legendPtr->focusGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
+ }
+ legendPtr->focusGC = newGC;
+
+ /*
+ * Update the layout of the graph (and redraw the elements) if any of
+ * the following legend options (all of which affect the size of the
+ * legend) have changed.
+ *
+ * -activeborderwidth, -borderwidth
+ * -border
+ * -font
+ * -hide
+ * -ipadx, -ipady, -padx, -pady
+ * -rows
+ *
+ * If the position of the legend changed to/from the default
+ * position, also indicate that a new layout is needed.
+ *
+ */
+ if (legendPtr->site == LEGEND_WINDOW) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ } else if (Blt_ConfigModified(configSpecs, "-*border*", "-*pad?",
+ "-hide", "-font", "-rows", (char *)NULL)) {
+ graphPtr->flags |= RESET_WORLD;
+ graphPtr->flags |= (REDRAW_WORLD | CACHE_DIRTY);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DestroyLegend --
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Resources associated with the legend are freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DestroyLegend(Graph *graphPtr)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ if (graphPtr->legend == NULL) {
+ return;
+ }
+
+ Blt_FreeOptions(configSpecs, (char *)legendPtr, graphPtr->display, 0);
+ Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->style);
+ Blt_Ts_FreeStyle(graphPtr->display, &legendPtr->titleStyle);
+ Blt_DestroyBindingTable(legendPtr->bindTable);
+
+ if (legendPtr->focusGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, legendPtr->focusGC);
+ }
+ if (legendPtr->timerToken != NULL) {
+ Tcl_DeleteTimerHandler(legendPtr->timerToken);
+ }
+ if (legendPtr->tkwin != NULL) {
+ Tk_DeleteSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING);
+ }
+ if (legendPtr->site == LEGEND_WINDOW) {
+ Tk_Window tkwin;
+
+ /* The graph may be in the process of being torn down */
+ if (legendPtr->cmdToken != NULL) {
+ Tcl_DeleteCommandFromToken(graphPtr->interp, legendPtr->cmdToken);
+ }
+ if (legendPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayLegend, legendPtr);
+ legendPtr->flags &= ~REDRAW_PENDING;
+ }
+ tkwin = legendPtr->tkwin;
+ legendPtr->tkwin = NULL;
+ if (tkwin != NULL) {
+ Tk_DeleteEventHandler(tkwin, ExposureMask | StructureNotifyMask,
+ LegendEventProc, graphPtr);
+ Tk_DestroyWindow(tkwin);
+ }
+ }
+ free(legendPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CreateLegend --
+ *
+ * Creates and initializes a legend structure with default settings
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+int
+Blt_CreateLegend(Graph *graphPtr)
+{
+ Legend *legendPtr;
+
+ legendPtr = calloc(1, sizeof(Legend));
+ graphPtr->legend = legendPtr;
+ legendPtr->graphPtr = graphPtr;
+ legendPtr->tkwin = graphPtr->tkwin;
+ legendPtr->xReq = legendPtr->yReq = -SHRT_MAX;
+ legendPtr->relief = TK_RELIEF_SUNKEN;
+ legendPtr->activeRelief = TK_RELIEF_FLAT;
+ legendPtr->entryBW = 2;
+ legendPtr->borderWidth = 2;
+ legendPtr->ixPad.side1 = legendPtr->ixPad.side2 = 1;
+ legendPtr->iyPad.side1 = legendPtr->iyPad.side2 = 1;
+ legendPtr->xPad.side1 = legendPtr->xPad.side2 = 1;
+ legendPtr->yPad.side1 = legendPtr->yPad.side2 = 1;
+ legendPtr->anchor = TK_ANCHOR_N;
+ legendPtr->site = LEGEND_RIGHT;
+ legendPtr->selectMode = SELECT_MODE_MULTIPLE;
+ Blt_Ts_InitStyle(legendPtr->style);
+ Blt_Ts_InitStyle(legendPtr->titleStyle);
+ legendPtr->style.justify = TK_JUSTIFY_LEFT;
+ legendPtr->style.anchor = TK_ANCHOR_NW;
+ legendPtr->titleStyle.justify = TK_JUSTIFY_LEFT;
+ legendPtr->titleStyle.anchor = TK_ANCHOR_NW;
+ legendPtr->bindTable = Blt_CreateBindingTable(graphPtr->interp,
+ graphPtr->tkwin, graphPtr, PickEntryProc, Blt_GraphTags);
+
+ Blt_InitHashTable(&legendPtr->selectTable, BLT_ONE_WORD_KEYS);
+ legendPtr->selected = Blt_Chain_Create();
+ Tk_CreateSelHandler(legendPtr->tkwin, XA_PRIMARY, XA_STRING,
+ SelectionProc, legendPtr, XA_STRING);
+ legendPtr->selRelief = TK_RELIEF_FLAT;
+ legendPtr->selBW = 1;
+ legendPtr->onTime = 600;
+ legendPtr->offTime = 300;
+ if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
+ "legend", "Legend", configSpecs, 0, (Tcl_Obj **)NULL,
+ (char *)legendPtr, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_ConfigureLegend(graphPtr);
+ return TCL_OK;
+}
+
+static Element *
+GetNextRow(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
+
+ col = focusPtr->col;
+ row = focusPtr->row + 1;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
+ }
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
+ }
+ }
+ return NULL;
+}
+
+static Element *
+GetNextColumn(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
+
+ col = focusPtr->col + 1;
+ row = focusPtr->row;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
+ }
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr; /* Don't go beyond legend boundaries. */
+ }
+ }
+ return NULL;
+}
+
+static Element *
+GetPreviousRow(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
+
+ col = focusPtr->col;
+ row = focusPtr->row - 1;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
+ }
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
+ }
+ }
+ return NULL;
+}
+
+static Element *
+GetPreviousColumn(Graph *graphPtr, Element *focusPtr)
+{
+ Blt_ChainLink link;
+ int row, col;
+
+ col = focusPtr->col - 1;
+ row = focusPtr->row;
+ for (link = focusPtr->link; link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label == NULL) {
+ continue;
+ }
+ if ((elemPtr->col == col) && (elemPtr->row == row)) {
+ return elemPtr;
+ }
+ }
+ return NULL;
+}
+
+static Element *
+GetFirstElement(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ return elemPtr;
+ }
+ }
+ return NULL;
+}
+
+static Element *
+GetLastElement(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->label != NULL) {
+ return elemPtr;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetElementFromObj --
+ *
+ * Parse an index into an entry and return either its value or an error.
+ *
+ * Results:
+ * A standard TCL result. If all went well, then *indexPtr is filled in
+ * with the character index (into entryPtr) corresponding to string. The
+ * index value is guaranteed to lie between 0 and the number of characters
+ * in the string, inclusive. If an error occurs then an error message is
+ * left in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+GetElementFromObj(Graph *graphPtr, Tcl_Obj *objPtr, Element **elemPtrPtr)
+{
+ Element *elemPtr;
+ Legend *legendPtr;
+ Tcl_Interp *interp;
+ char c;
+ const char *string;
+ int last;
+
+ legendPtr = graphPtr->legend;
+ interp = graphPtr->interp;
+ string = Tcl_GetString(objPtr);
+ c = string[0];
+ elemPtr = NULL;
+
+ last = Blt_Chain_GetLength(graphPtr->elements.displayList) - 1;
+ if ((c == 'a') && (strcmp(string, "anchor") == 0)) {
+ elemPtr = legendPtr->selAnchorPtr;
+ } else if ((c == 'c') && (strcmp(string, "current") == 0)) {
+ elemPtr = (Element *)Blt_GetCurrentItem(legendPtr->bindTable);
+ } else if ((c == 'f') && (strcmp(string, "first") == 0)) {
+ elemPtr = GetFirstElement(graphPtr);
+ } else if ((c == 'f') && (strcmp(string, "focus") == 0)) {
+ elemPtr = legendPtr->focusPtr;
+ } else if ((c == 'l') && (strcmp(string, "last") == 0)) {
+ elemPtr = GetLastElement(graphPtr);
+ } else if ((c == 'e') && (strcmp(string, "end") == 0)) {
+ elemPtr = GetLastElement(graphPtr);
+ } else if ((c == 'n') && (strcmp(string, "next.row") == 0)) {
+ elemPtr = GetNextRow(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'n') && (strcmp(string, "next.column") == 0)) {
+ elemPtr = GetNextColumn(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'p') && (strcmp(string, "previous.row") == 0)) {
+ elemPtr = GetPreviousRow(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 'p') && (strcmp(string, "previous.column") == 0)) {
+ elemPtr = GetPreviousColumn(graphPtr, legendPtr->focusPtr);
+ } else if ((c == 's') && (strcmp(string, "sel.first") == 0)) {
+ elemPtr = legendPtr->selFirstPtr;
+ } else if ((c == 's') && (strcmp(string, "sel.last") == 0)) {
+ elemPtr = legendPtr->selLastPtr;
+ } else if (c == '@') {
+ int x, y;
+
+ if (Blt_GetXY(interp, legendPtr->tkwin, string, &x, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ elemPtr = (Element *)PickEntryProc(graphPtr, x, y, NULL);
+ } else {
+ if (Blt_GetElement(interp, graphPtr, objPtr, &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (elemPtr->link == NULL) {
+ Tcl_AppendResult(interp, "bad legend index \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (elemPtr->label == NULL) {
+ elemPtr = NULL;
+ }
+ }
+ *elemPtrPtr = elemPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectRange --
+ *
+ * Sets the selection flag for a range of nodes. The range is determined
+ * by two pointers which designate the first/last nodes of the range.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+SelectRange(Legend *legendPtr, Element *fromPtr, Element *toPtr)
+{
+
+ if (Blt_Chain_IsBefore(fromPtr->link, toPtr->link)) {
+ Blt_ChainLink link;
+
+ for (link = fromPtr->link; link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ SelectEntry(legendPtr, elemPtr);
+ if (link == toPtr->link) {
+ break;
+ }
+ }
+ } else {
+ Blt_ChainLink link;
+
+ for (link = fromPtr->link; link != NULL;
+ link = Blt_Chain_PrevLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ SelectEntry(legendPtr, elemPtr);
+ if (link == toPtr->link) {
+ break;
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ActivateOp --
+ *
+ * Activates a particular label in the legend.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ActivateOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ unsigned int active, redraw;
+ const char *string;
+ int i;
+
+ string = Tcl_GetString(objv[2]);
+ active = (string[0] == 'a') ? LABEL_ACTIVE : 0;
+ redraw = FALSE;
+ for (i = 3; i < objc; i++) {
+ Blt_ChainLink link;
+ const char *pattern;
+
+ pattern = Tcl_GetString(objv[i]);
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (Tcl_StringMatch(elemPtr->obj.name, pattern)) {
+ fprintf(stderr, "legend %s(%s) %s is currently %d\n",
+ string, pattern, elemPtr->obj.name,
+ (elemPtr->flags & LABEL_ACTIVE));
+ if (active) {
+ if ((elemPtr->flags & LABEL_ACTIVE) == 0) {
+ elemPtr->flags |= LABEL_ACTIVE;
+ redraw = TRUE;
+ }
+ } else {
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ elemPtr->flags &= ~LABEL_ACTIVE;
+ redraw = TRUE;
+ }
+ }
+ fprintf(stderr, "legend %s(%s) %s is now %d\n",
+ string, pattern, elemPtr->obj.name,
+ (elemPtr->flags & LABEL_ACTIVE));
+ }
+ }
+ }
+ if ((redraw) && ((legendPtr->flags & HIDE) == 0)) {
+ /*
+ * See if how much we need to draw. If the graph is already scheduled
+ * for a redraw, just make sure the right flags are set. Otherwise
+ * redraw only the legend: it's either in an external window or it's
+ * the only thing that need updating.
+ */
+ if ((legendPtr->site != LEGEND_WINDOW) &&
+ (graphPtr->flags & REDRAW_PENDING)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ graphPtr->flags |= REDRAW_WORLD; /* Redraw entire graph. */
+ } else {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ }
+ {
+ Blt_ChainLink link;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ /* List active elements in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->flags & LABEL_ACTIVE) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BindOp --
+ *
+ * .t bind index sequence command
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+BindOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->elements.tagTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ const char *tagName;
+ Tcl_Obj *objPtr;
+
+ tagName = Blt_GetHashKey(&graphPtr->elements.tagTable, hPtr);
+ objPtr = Tcl_NewStringObj(tagName, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->legend->bindTable,
+ Blt_MakeElementTag(graphPtr, Tcl_GetString(objv[3])), objc - 4,
+ objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ * Queries or resets options for the legend.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+CgetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)graphPtr->legend, objv[3], 0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Queries or resets options for the legend.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int flags = BLT_CONFIG_OBJV_ONLY;
+ Legend *legendPtr;
+
+ legendPtr = graphPtr->legend;
+ if (objc == 3) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)legendPtr, (Tcl_Obj *)NULL, flags);
+ } else if (objc == 4) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)legendPtr, objv[3], flags);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc - 3, objv + 3, (char *)legendPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_ConfigureLegend(graphPtr);
+ return TCL_OK;
+}
+
+
+/*ARGSUSED*/
+static int
+CurselectionOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (legendPtr->flags & SELECT_SORTED) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(legendPtr->selected); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+ Tcl_Obj *objPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ } else {
+ Blt_ChainLink link;
+
+ /* List of selected entries is in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+
+ if (EntryIsSelected(legendPtr, elemPtr)) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewStringObj(elemPtr->obj.name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+FocusOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ if (objc == 4) {
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((elemPtr != NULL) && (elemPtr != legendPtr->focusPtr)) {
+ /* Changing focus can only affect the visible entries. The entry
+ * layout stays the same. */
+ legendPtr->focusPtr = elemPtr;
+ }
+ Blt_SetFocusItem(legendPtr->bindTable, legendPtr->focusPtr,
+ CID_LEGEND_ENTRY);
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ if (legendPtr->focusPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ legendPtr->focusPtr->obj.name, -1);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetOp --
+ *
+ * Find the legend entry from the given argument. The argument can be
+ * either a screen position "@x,y" or the name of an element.
+ *
+ * I don't know how useful it is to test with the name of an element.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+GetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ if (((legendPtr->flags & HIDE) == 0) && (legendPtr->nEntries > 0)) {
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[3], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (elemPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name,-1);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionAnchorOp --
+ *
+ * Sets the selection anchor to the element given by a index. The
+ * selection anchor is the end of the selection that is fixed while
+ * dragging out a selection with the mouse. The index "anchor" may be
+ * used to refer to the anchor element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionAnchorOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Set both the anchor and the mark. Indicates that a single entry
+ * is selected. */
+ legendPtr->selAnchorPtr = elemPtr;
+ legendPtr->selMarkPtr = NULL;
+ if (elemPtr != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionClearallOp
+ *
+ * Clears the entire selection.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionClearallOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+
+ ClearSelection(legendPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionIncludesOp
+ *
+ * Returns 1 if the element indicated by index is currently
+ * selected, 0 if it isn't.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionIncludesOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+ int bool;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ bool = EntryIsSelected(legendPtr, elemPtr);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionMarkOp --
+ *
+ * Sets the selection mark to the element given by a index. The
+ * selection anchor is the end of the selection that is movable while
+ * dragging out a selection with the mouse. The index "mark" may be used
+ * to refer to the anchor element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionMarkOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Element *elemPtr;
+
+ if (GetElementFromObj(graphPtr, objv[4], &elemPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (legendPtr->selAnchorPtr == NULL) {
+ Tcl_AppendResult(interp, "selection anchor must be set first",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (legendPtr->selMarkPtr != elemPtr) {
+ Blt_ChainLink link, next;
+
+ /* Deselect entry from the list all the way back to the anchor. */
+ for (link = Blt_Chain_LastLink(legendPtr->selected); link != NULL;
+ link = next) {
+ Element *selectPtr;
+
+ next = Blt_Chain_PrevLink(link);
+ selectPtr = Blt_Chain_GetValue(link);
+ if (selectPtr == legendPtr->selAnchorPtr) {
+ break;
+ }
+ DeselectElement(legendPtr, selectPtr);
+ }
+ legendPtr->flags &= ~SELECT_BLTMASK;
+ legendPtr->flags |= SELECT_SET;
+ SelectRange(legendPtr, legendPtr->selAnchorPtr, elemPtr);
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), elemPtr->obj.name, -1);
+ legendPtr->selMarkPtr = elemPtr;
+
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionPresentOp
+ *
+ * Returns 1 if there is a selection and 0 if it isn't.
+ *
+ * Results:
+ * A standard TCL result. interp->result will contain a boolean string
+ * indicating if there is a selection.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionPresentOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ int bool;
+
+ bool = (Blt_Chain_GetLength(legendPtr->selected) > 0);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionSetOp
+ *
+ * Selects, deselects, or toggles all of the elements in the range
+ * between first and last, inclusive, without affecting the selection
+ * state of elements outside that range.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ * .g legend selection set first last
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SelectionSetOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ Legend *legendPtr = graphPtr->legend;
+ Element *firstPtr, *lastPtr;
+ const char *string;
+
+ legendPtr->flags &= ~SELECT_BLTMASK;
+ string = Tcl_GetString(objv[3]);
+ switch (string[0]) {
+ case 's':
+ legendPtr->flags |= SELECT_SET;
+ break;
+ case 'c':
+ legendPtr->flags |= SELECT_CLEAR;
+ break;
+ case 't':
+ legendPtr->flags |= SELECT_TOGGLE;
+ break;
+ }
+ if (GetElementFromObj(graphPtr, objv[4], &firstPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((firstPtr->flags & HIDE) && ((legendPtr->flags & SELECT_CLEAR)==0)) {
+ Tcl_AppendResult(interp, "can't select hidden node \"",
+ Tcl_GetString(objv[4]), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ lastPtr = firstPtr;
+ if (objc > 5) {
+ if (GetElementFromObj(graphPtr, objv[5], &lastPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((lastPtr->flags & HIDE) &&
+ ((legendPtr->flags & SELECT_CLEAR) == 0)) {
+ Tcl_AppendResult(interp, "can't select hidden node \"",
+ Tcl_GetString(objv[5]), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (firstPtr == lastPtr) {
+ SelectEntry(legendPtr, firstPtr);
+ } else {
+ SelectRange(legendPtr, firstPtr, lastPtr);
+ }
+ /* Set both the anchor and the mark. Indicates that a single entry is
+ * selected. */
+ if (legendPtr->selAnchorPtr == NULL) {
+ legendPtr->selAnchorPtr = firstPtr;
+ }
+ if (legendPtr->flags & SELECT_EXPORT) {
+ Tk_OwnSelection(legendPtr->tkwin, XA_PRIMARY, LostSelectionProc,
+ legendPtr);
+ }
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ if (legendPtr->selectCmd != NULL) {
+ EventuallyInvokeSelectCmd(legendPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionOp --
+ *
+ * This procedure handles the individual options for text selections.
+ * The selected text is designated by start and end indices into the text
+ * pool. The selected segment has both a anchored and unanchored ends.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The selection changes.
+ *
+ * .g legend selection anchor
+ *---------------------------------------------------------------------------
+ */
+static Blt_OpSpec selectionOps[] =
+{
+ {"anchor", 1, SelectionAnchorOp, 5, 5, "elem",},
+ {"clear", 5, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+ {"clearall", 6, SelectionClearallOp, 4, 4, "",},
+ {"includes", 1, SelectionIncludesOp, 5, 5, "elem",},
+ {"mark", 1, SelectionMarkOp, 5, 5, "elem",},
+ {"present", 1, SelectionPresentOp, 4, 4, "",},
+ {"set", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+ {"toggle", 1, SelectionSetOp, 5, 6, "firstElem ?lastElem?",},
+};
+static int nSelectionOps = sizeof(selectionOps) / sizeof(Blt_OpSpec);
+
+static int
+SelectionOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ GraphLegendProc *proc;
+ int result;
+
+ proc = Blt_GetOpFromObj(interp, nSelectionOps, selectionOps, BLT_OP_ARG3,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ result = (*proc) (graphPtr, interp, objc, objv);
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_LegendOp --
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Legend is possibly redrawn.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Blt_OpSpec legendOps[] =
+{
+ {"activate", 1, ActivateOp, 3, 0, "?pattern?...",},
+ {"bind", 1, BindOp, 3, 6, "elem sequence command",},
+ {"cget", 2, CgetOp, 4, 4, "option",},
+ {"configure", 2, ConfigureOp, 3, 0, "?option value?...",},
+ {"curselection", 2, CurselectionOp, 3, 3, "",},
+ {"deactivate", 1, ActivateOp, 3, 0, "?pattern?...",},
+ {"focus", 1, FocusOp, 4, 4, "elem",},
+ {"get", 1, GetOp, 4, 4, "elem",},
+ // {"icon", 1, IconOp, 5, 5, "elem image",},
+ {"selection", 1, SelectionOp, 3, 0, "args"},
+};
+static int nLegendOps = sizeof(legendOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_LegendOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphLegendProc *proc;
+
+ proc = Blt_GetOpFromObj(interp, nLegendOps, legendOps, BLT_OP_ARG2,
+ objc, objv,0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ return (*proc) (graphPtr, interp, objc, objv);
+}
+
+int
+Blt_Legend_Site(Graph *graphPtr)
+{
+ return graphPtr->legend->site;
+}
+
+int
+Blt_Legend_Width(Graph *graphPtr)
+{
+ return graphPtr->legend->width;
+}
+
+int
+Blt_Legend_Height(Graph *graphPtr)
+{
+ return graphPtr->legend->height;
+}
+
+int
+Blt_Legend_IsHidden(Graph *graphPtr)
+{
+ return (graphPtr->legend->flags & HIDE);
+}
+
+int
+Blt_Legend_IsRaised(Graph *graphPtr)
+{
+ return (graphPtr->legend->flags & RAISED);
+}
+
+int
+Blt_Legend_X(Graph *graphPtr)
+{
+ return graphPtr->legend->x;
+}
+
+int
+Blt_Legend_Y(Graph *graphPtr)
+{
+ return graphPtr->legend->y;
+}
+
+void
+Blt_Legend_RemoveElement(Graph *graphPtr, Element *elemPtr)
+{
+ Blt_DeleteBindings(graphPtr->legend->bindTable, elemPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SelectionProc --
+ *
+ * This procedure is called back by Tk when the selection is requested by
+ * someone. It returns part or all of the selection in a buffer provided
+ * by the caller.
+ *
+ * Results:
+ * The return value is the number of non-NULL bytes stored at buffer.
+ * Buffer is filled (or partially filled) with a NUL-terminated string
+ * containing part or all of the selection, as given by offset and
+ * maxBytes.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+SelectionProc(
+ ClientData clientData, /* Information about the widget. */
+ int offset, /* Offset within selection of first
+ * character to be returned. */
+ char *buffer, /* Location in which to place
+ * selection. */
+ int maxBytes) /* Maximum number of bytes to place at
+ * buffer, not including terminating
+ * NULL character. */
+{
+ Legend *legendPtr = clientData;
+ int nBytes;
+ Tcl_DString dString;
+
+ if ((legendPtr->flags & SELECT_EXPORT) == 0) {
+ return -1;
+ }
+ /* Retrieve the names of the selected entries. */
+ Tcl_DStringInit(&dString);
+ if (legendPtr->flags & SELECT_SORTED) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(legendPtr->selected);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
+ Tcl_DStringAppend(&dString, "\n", -1);
+ }
+ } else {
+ Blt_ChainLink link;
+ Graph *graphPtr;
+
+ graphPtr = legendPtr->graphPtr;
+ /* List of selected entries is in stacking order. */
+ for (link = Blt_Chain_FirstLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Element *elemPtr;
+
+ elemPtr = Blt_Chain_GetValue(link);
+ if (EntryIsSelected(legendPtr, elemPtr)) {
+ Tcl_DStringAppend(&dString, elemPtr->obj.name, -1);
+ Tcl_DStringAppend(&dString, "\n", -1);
+ }
+ }
+ }
+ nBytes = Tcl_DStringLength(&dString) - offset;
+ strncpy(buffer, Tcl_DStringValue(&dString) + offset, maxBytes);
+ Tcl_DStringFree(&dString);
+ buffer[maxBytes] = '\0';
+ return MIN(nBytes, maxBytes);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BlinkCursorProc --
+ *
+ * This procedure is called as a timer handler to blink the insertion
+ * cursor off and on.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The cursor gets turned on or off, redisplay gets invoked, and this
+ * procedure reschedules itself.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+BlinkCursorProc(ClientData clientData)
+{
+ Graph *graphPtr = clientData;
+ Legend *legendPtr;
+
+ legendPtr = graphPtr->legend;
+ if (!(legendPtr->flags & FOCUS) || (legendPtr->offTime == 0)) {
+ return;
+ }
+ if (legendPtr->active) {
+ int time;
+
+ legendPtr->cursorOn ^= 1;
+ time = (legendPtr->cursorOn) ? legendPtr->onTime : legendPtr->offTime;
+ legendPtr->timerToken = Tcl_CreateTimerHandler(time, BlinkCursorProc,
+ graphPtr);
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+}
diff --git a/tlt3.0/bltGrLegd.h b/tlt3.0/bltGrLegd.h
new file mode 100644
index 0000000..e12dd78
--- /dev/null
+++ b/tlt3.0/bltGrLegd.h
@@ -0,0 +1,60 @@
+/*
+ * bltGrLegd.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GR_LEGEND_H
+#define _BLT_GR_LEGEND_H
+
+#define LEGEND_RIGHT (1<<0) /* Right margin */
+#define LEGEND_LEFT (1<<1) /* Left margin */
+#define LEGEND_BOTTOM (1<<2) /* Bottom margin */
+#define LEGEND_TOP (1<<3) /* Top margin, below the graph title. */
+#define LEGEND_PLOT (1<<4) /* Plot area */
+#define LEGEND_XY (1<<5) /* Screen coordinates in the plotting
+ * area. */
+#define LEGEND_WINDOW (1<<6) /* External window. */
+#define LEGEND_MARGIN_MASK \
+ (LEGEND_RIGHT | LEGEND_LEFT | LEGEND_BOTTOM | LEGEND_TOP)
+#define LEGEND_PLOTAREA_MASK (LEGEND_PLOT | LEGEND_XY)
+
+extern int Blt_CreateLegend(Graph *graphPtr);
+extern void Blt_DestroyLegend(Graph *graphPtr);
+extern void Blt_DrawLegend(Graph *graphPtr, Drawable drawable);
+extern void Blt_MapLegend(Graph *graphPtr, int width, int height);
+extern int Blt_LegendOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+extern int Blt_Legend_Site(Graph *graphPtr);
+extern int Blt_Legend_Width(Graph *graphPtr);
+extern int Blt_Legend_Height(Graph *graphPtr);
+extern int Blt_Legend_IsHidden(Graph *graphPtr);
+extern int Blt_Legend_IsRaised(Graph *graphPtr);
+extern int Blt_Legend_X(Graph *graphPtr);
+extern int Blt_Legend_Y(Graph *graphPtr);
+extern void Blt_Legend_RemoveElement(Graph *graphPtr, Element *elemPtr);
+extern void Blt_Legend_EventuallyRedraw(Graph *graphPtr);
+
+#endif /* BLT_GR_LEGEND_H */
diff --git a/tlt3.0/bltGrLine.c b/tlt3.0/bltGrLine.c
new file mode 100644
index 0000000..d4f6a50
--- /dev/null
+++ b/tlt3.0/bltGrLine.c
@@ -0,0 +1,4798 @@
+
+/*
+ * bltGrLine.c --
+ *
+ * This module implements line graph and stripchart elements for the BLT graph
+ * widget.
+ *
+ * Copyright (c) 1993 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltSpline.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltGrElem.h"
+#include "bltBitmap.h"
+
+#define COLOR_DEFAULT (XColor *)1
+#define PATTERN_SOLID ((Pixmap)1)
+
+#define PEN_INCREASING 1 /* Draw line segments for only those
+ * data points whose abscissas are
+ * monotonically increasing in
+ * order. */
+#define PEN_DECREASING 2 /* Lines will be drawn between only
+ * those points whose abscissas are
+ * decreasing in order. */
+
+#define PEN_BOTH_DIRECTIONS (PEN_INCREASING | PEN_DECREASING)
+
+/* Lines will be drawn between points regardless of the ordering of the
+ * abscissas */
+
+#define BROKEN_TRACE(dir,last,next) \
+ (((((dir) & PEN_DECREASING) == 0) && ((next) < (last))) || \
+ ((((dir) & PEN_INCREASING) == 0) && ((next) > (last))))
+
+#define DRAW_SYMBOL(linePtr) \
+ (((linePtr)->symbolCounter % (linePtr)->symbolInterval) == 0)
+
+typedef enum {
+ PEN_SMOOTH_LINEAR, /* Line segments */
+ PEN_SMOOTH_STEP, /* Step-and-hold */
+ PEN_SMOOTH_NATURAL, /* Natural cubic spline */
+ PEN_SMOOTH_QUADRATIC, /* Quadratic spline */
+ PEN_SMOOTH_CATROM, /* Catrom parametric spline */
+ PEN_SMOOTH_LAST /* Sentinel */
+} Smoothing;
+
+typedef struct {
+ const char *name;
+ Smoothing value;
+} SmoothingInfo;
+
+static SmoothingInfo smoothingInfo[] = {
+ { "none", PEN_SMOOTH_LINEAR },
+ { "linear", PEN_SMOOTH_LINEAR },
+ { "step", PEN_SMOOTH_STEP },
+ { "natural", PEN_SMOOTH_NATURAL },
+ { "cubic", PEN_SMOOTH_NATURAL },
+ { "quadratic", PEN_SMOOTH_QUADRATIC },
+ { "catrom", PEN_SMOOTH_CATROM },
+ { (char *)NULL, PEN_SMOOTH_LAST }
+};
+
+
+typedef struct {
+ Point2d *screenPts; /* Array of transformed coordinates */
+ int nScreenPts; /* Number of coordinates */
+ int *styleMap; /* Index of pen styles */
+ int *map; /* Maps segments/traces to data
+ * points */
+} MapInfo;
+
+/* Symbol types for line elements */
+typedef enum {
+ SYMBOL_NONE,
+ SYMBOL_SQUARE,
+ SYMBOL_CIRCLE,
+ SYMBOL_DIAMOND,
+ SYMBOL_PLUS,
+ SYMBOL_CROSS,
+ SYMBOL_SPLUS,
+ SYMBOL_SCROSS,
+ SYMBOL_TRIANGLE,
+ SYMBOL_ARROW,
+ SYMBOL_BITMAP,
+ SYMBOL_IMAGE
+} SymbolType;
+
+typedef struct {
+ const char *name;
+ unsigned int minChars;
+ SymbolType type;
+} GraphSymbolType;
+
+static GraphSymbolType graphSymbols[] = {
+ { "arrow", 1, SYMBOL_ARROW, },
+ { "circle", 2, SYMBOL_CIRCLE, },
+ { "cross", 2, SYMBOL_CROSS, },
+ { "diamond", 1, SYMBOL_DIAMOND, },
+ { "none", 1, SYMBOL_NONE, },
+ { "plus", 1, SYMBOL_PLUS, },
+ { "scross", 2, SYMBOL_SCROSS, },
+ { "splus", 2, SYMBOL_SPLUS, },
+ { "square", 2, SYMBOL_SQUARE, },
+ { "triangle", 1, SYMBOL_TRIANGLE, },
+ { NULL, 0, 0 },
+};
+
+typedef struct {
+ SymbolType type; /* Type of symbol to be drawn/printed */
+
+ int size; /* Requested size of symbol in pixels */
+
+ XColor *outlineColor; /* Outline color */
+
+ int outlineWidth; /* Width of the outline */
+
+ GC outlineGC; /* Outline graphics context */
+
+ XColor *fillColor; /* Normal fill color */
+
+ GC fillGC; /* Fill graphics context */
+
+ Tk_Image image; /* This is used of image symbols. */
+
+ /* The last two fields are used only for bitmap symbols. */
+
+ Pixmap bitmap; /* Bitmap to determine
+ * foreground/background pixels of the
+ * symbol */
+ Pixmap mask; /* Bitmap representing the transparent
+ * pixels of the symbol */
+} Symbol;
+
+typedef struct {
+ int start; /* Index into the X-Y coordinate arrays
+ * indicating where trace starts. */
+ GraphPoints screenPts; /* Array of screen coordinates
+ * (malloc-ed) representing the
+ * trace. */
+} bltTrace;
+
+typedef struct {
+ const char *name; /* Pen style identifier. If NULL pen
+ * was statically allocated. */
+ ClassId classId; /* Type of pen */
+ const char *typeId; /* String token identifying the type of
+ * pen */
+ unsigned int flags; /* Indicates if the pen element is
+ * active or normal */
+ int refCount; /* Reference count for elements using
+ * this pen. */
+ Blt_HashEntry *hashPtr;
+
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications */
+
+ PenConfigureProc *configProc;
+ PenDestroyProc *destroyProc;
+ Graph *graphPtr; /* Graph that the pen is associated
+ * with. */
+
+ /* Symbol attributes. */
+ Symbol symbol; /* Element symbol type */
+
+ /* Trace attributes. */
+ int traceWidth; /* Width of the line segments. If
+ * lineWidth is 0, no line will be
+ * drawn, only symbols. */
+
+ Blt_Dashes traceDashes; /* Dash on-off list value */
+
+ XColor *traceColor; /* Line segment color */
+
+ XColor *traceOffColor; /* Line segment dash gap color */
+
+ GC traceGC; /* Line segment graphics context */
+
+ /* Error bar attributes. */
+ int errorBarShow; /* Describes which error bars to display:
+ * none, x, y, or * both. */
+
+ int errorBarLineWidth; /* Width of the error bar segments. */
+
+ int errorBarCapWidth; /* Width of the cap on error bars. */
+
+ XColor *errorBarColor; /* Color of the error bar. */
+
+ GC errorBarGC; /* Error bar graphics context. */
+
+ /* Show value attributes. */
+ int valueShow; /* Indicates whether to display data
+ * value. Values are x, y, both, or
+ * none. */
+ const char *valueFormat; /* A printf format string. */
+
+ TextStyle valueStyle; /* Text attributes (color, font,
+ * rotation, etc.) of the value. */
+} LinePen;
+
+typedef struct {
+ Weight weight; /* Weight range where this pen is
+ * valid. */
+ LinePen *penPtr; /* Pen to use. */
+ GraphPoints symbolPts;
+
+ GraphSegments lines; /* Points to start of the line segments
+ * for this pen. */
+ GraphSegments xeb, yeb; /* X and Y axis error bars. */
+
+ int symbolSize; /* Size of the pen's symbol scaled to
+ * the current graph size. */
+ int errorBarCapWidth; /* Length of the cap ends on each error
+ * bar. */
+} LineStyle;
+
+typedef struct {
+ GraphObj obj; /* Must be first field in element. */
+ unsigned int flags;
+ Blt_HashEntry *hashPtr;
+
+ /* Fields specific to elements. */
+ const char *label; /* Label displayed in legend */
+ unsigned short row, col; /* Position of the entry in the
+ * legend. */
+ int legendRelief; /* Relief of label in legend. */
+ Axis2d axes; /* X-axis and Y-axis mapping the
+ * element */
+ ElemValues x, y, w; /* Contains array of floating point
+ * graph coordinate values. Also holds
+ * min/max * and the number of
+ * coordinates */
+ int *activeIndices; /* Array of indices (malloc-ed) which
+ * indicate which data points are active
+ * (drawn * with "active" colors). */
+ int nActiveIndices; /* Number of active data points.
+ * Special case: if nActiveIndices < 0
+ * and the * active bit is set in
+ * "flags", then all data points are
+ * drawn active. */
+ ElementProcs *procsPtr;
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications. */
+ LinePen *activePenPtr; /* Standard Pens */
+ LinePen *normalPenPtr;
+ LinePen *builtinPenPtr;
+ Blt_Chain styles; /* Palette of pens. */
+
+ /* Symbol scaling */
+ int scaleSymbols; /* If non-zero, the symbols will scale
+ * in size as the graph is zoomed
+ * in/out. */
+
+ double xRange, yRange; /* Initial X-axis and Y-axis ranges:
+ * used to scale the size of element's
+ * symbol. */
+ int state;
+ Blt_ChainLink link; /* Element's link in display list. */
+
+ /* The line element specific fields start here. */
+
+ ElemValues xError; /* Relative/symmetric X error values. */
+ ElemValues yError; /* Relative/symmetric Y error values. */
+ ElemValues xHigh, xLow; /* Absolute/asymmetric X-coordinate
+ * high/low error values. */
+ ElemValues yHigh, yLow; /* Absolute/asymmetric Y-coordinate
+ * high/low error values. */
+ LinePen builtinPen;
+ int errorBarCapWidth; /* Length of cap on error bars */
+
+ /* Line smoothing */
+ Smoothing reqSmooth; /* Requested smoothing function to use
+ * for connecting the data points */
+ Smoothing smooth; /* Smoothing function used. */
+ float rTolerance; /* Tolerance to reduce the number of
+ * points displayed. */
+
+ /* Drawing-related data structures. */
+
+ /* Area-under-curve fill attributes. */
+ XColor *fillFgColor;
+ XColor *fillBgColor;
+ GC fillGC;
+
+ Blt_Background fillBg; /* Background for fill area. */
+
+ Point2d *fillPts; /* Array of points used to draw polygon
+ * to fill area under the curve */
+ int nFillPts;
+
+ /* Symbol points */
+ GraphPoints symbolPts;
+
+ /* Active symbol points */
+ GraphPoints activePts;
+ GraphSegments xeb, yeb; /* Point to start of this pen's X-error
+ * bar segments in the element's
+ * array. */
+ int reqMaxSymbols;
+ int symbolInterval;
+ int symbolCounter;
+
+ /* X-Y graph-specific fields */
+
+ int penDir; /* Indicates if a change in the pen
+ * direction should be considered a
+ * retrace (line segment is not
+ * drawn). */
+ Blt_Chain traces; /* List of traces (a trace is a series
+ * of contiguous line segments). New
+ * traces are generated when either
+ * the next segment changes the pen
+ * direction, or the end point is
+ * clipped by the plotting area. */
+
+ /* Stripchart-specific fields */
+
+ GraphSegments lines; /* Holds the the line segments of the
+ * element trace. The segments are
+ * grouped by pen style. */
+} LineElement;
+
+static Blt_OptionParseProc ObjToSmoothProc;
+static Blt_OptionPrintProc SmoothToObjProc;
+static Blt_CustomOption smoothOption =
+{
+ ObjToSmoothProc, SmoothToObjProc, NULL, (ClientData)0
+};
+
+static Blt_OptionParseProc ObjToPenDirProc;
+static Blt_OptionPrintProc PenDirToObjProc;
+static Blt_CustomOption penDirOption =
+{
+ ObjToPenDirProc, PenDirToObjProc, NULL, (ClientData)0
+};
+
+static Blt_OptionFreeProc FreeSymbolProc;
+static Blt_OptionParseProc ObjToSymbolProc;
+static Blt_OptionPrintProc SymbolToObjProc;
+static Blt_CustomOption symbolOption =
+{
+ ObjToSymbolProc, SymbolToObjProc, FreeSymbolProc, (ClientData)0
+};
+
+extern Blt_CustomOption bltLineStylesOption;
+extern Blt_CustomOption bltColorOption;
+extern Blt_CustomOption bltValuesOption;
+extern Blt_CustomOption bltValuePairsOption;
+extern Blt_CustomOption bltLinePenOption;
+extern Blt_CustomOption bltXAxisOption;
+extern Blt_CustomOption bltYAxisOption;
+
+#define DEF_LINE_ACTIVE_PEN "activeLine"
+#define DEF_LINE_AXIS_X "x"
+#define DEF_LINE_AXIS_Y "y"
+#define DEF_LINE_DASHES (char *)NULL
+#define DEF_LINE_DATA (char *)NULL
+#define DEF_LINE_FILL_COLOR "defcolor"
+#define DEF_LINE_HIDE "no"
+#define DEF_LINE_LABEL (char *)NULL
+#define DEF_LINE_LABEL_RELIEF "flat"
+#define DEF_LINE_MAX_SYMBOLS "0"
+#define DEF_LINE_OFFDASH_COLOR (char *)NULL
+#define DEF_LINE_OUTLINE_COLOR "defcolor"
+#define DEF_LINE_OUTLINE_WIDTH "1"
+#define DEF_LINE_PATTERN_BG (char *)NULL
+#define DEF_LINE_PATTERN_FG "black"
+#define DEF_LINE_PEN_COLOR RGB_NAVYBLUE
+#define DEF_LINE_PEN_DIRECTION "both"
+#define DEF_LINE_PEN_WIDTH "1"
+#define DEF_LINE_PIXELS "0.1i"
+#define DEF_LINE_REDUCE "0.0"
+#define DEF_LINE_SCALE_SYMBOLS "yes"
+#define DEF_LINE_SMOOTH "linear"
+#define DEF_LINE_STATE "normal"
+#define DEF_LINE_STIPPLE (char *)NULL
+#define DEF_LINE_STYLES ""
+#define DEF_LINE_SYMBOL "circle"
+#define DEF_LINE_TAGS "all"
+#define DEF_LINE_X_DATA (char *)NULL
+#define DEF_LINE_Y_DATA (char *)NULL
+
+#define DEF_LINE_ERRORBAR_COLOR "defcolor"
+#define DEF_LINE_ERRORBAR_LINE_WIDTH "2"
+#define DEF_LINE_ERRORBAR_CAP_WIDTH "2"
+#define DEF_LINE_SHOW_ERRORBARS "both"
+
+#define DEF_PEN_ACTIVE_COLOR RGB_BLUE
+#define DEF_PEN_DASHES (char *)NULL
+#define DEF_PEN_FILL_COLOR "defcolor"
+#define DEF_PEN_LINE_WIDTH "1"
+#define DEF_PEN_NORMAL_COLOR RGB_NAVYBLUE
+#define DEF_PEN_OFFDASH_COLOR (char *)NULL
+#define DEF_PEN_OUTLINE_COLOR "defcolor"
+#define DEF_PEN_OUTLINE_WIDTH "1"
+#define DEF_PEN_PIXELS "0.1i"
+#define DEF_PEN_SYMBOL "circle"
+#define DEF_PEN_TYPE "line"
+#define DEF_PEN_VALUE_ANCHOR "s"
+#define DEF_PEN_VALUE_COLOR RGB_BLACK
+#define DEF_PEN_VALUE_FONT STD_FONT_NUMBERS
+#define DEF_PEN_VALUE_FORMAT "%g"
+#define DEF_PEN_VALUE_ANGLE (char *)NULL
+#define DEF_PEN_SHOW_VALUES "no"
+
+static Blt_ConfigSpec lineElemConfigSpecs[] =
+{
+ {BLT_CONFIG_CUSTOM, "-activepen", "activePen", "ActivePen",
+ DEF_LINE_ACTIVE_PEN, Blt_Offset(LineElement, activePenPtr),
+ BLT_CONFIG_NULL_OK, &bltLinePenOption},
+ {BLT_CONFIG_COLOR, "-areaforeground", "areaForeground", "AreaForeground",
+ DEF_LINE_PATTERN_FG, Blt_Offset(LineElement, fillFgColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BACKGROUND, "-areabackground", "areaBackground",
+ "AreaBackground", DEF_LINE_PATTERN_BG, Blt_Offset(LineElement, fillBg),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_LINE_TAGS,
+ Blt_Offset(LineElement, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-color", "color", "Color", DEF_LINE_PEN_COLOR,
+ Blt_Offset(LineElement, builtinPen.traceColor), 0},
+ {BLT_CONFIG_DASHES, "-dashes", "dashes", "Dashes", DEF_LINE_DASHES,
+ Blt_Offset(LineElement, builtinPen.traceDashes), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-data", "data", "Data", DEF_LINE_DATA, 0, 0,
+ &bltValuePairsOption},
+ {BLT_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
+ DEF_LINE_ERRORBAR_COLOR,
+ Blt_Offset(LineElement, builtinPen.errorBarColor), 0, &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG,"-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
+ DEF_LINE_ERRORBAR_LINE_WIDTH,
+ Blt_Offset(LineElement, builtinPen.errorBarLineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarcap", "errorBarCap", "ErrorBarCap",
+ DEF_LINE_ERRORBAR_CAP_WIDTH,
+ Blt_Offset(LineElement, builtinPen.errorBarCapWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-fill", "fill", "Fill", DEF_LINE_FILL_COLOR,
+ Blt_Offset(LineElement, builtinPen.symbol.fillColor),
+ BLT_CONFIG_NULL_OK, &bltColorOption},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_LINE_HIDE,
+ Blt_Offset(LineElement, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_STRING, "-label", "label", "Label", (char *)NULL,
+ Blt_Offset(LineElement, label), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_RELIEF, "-legendrelief", "legendRelief", "LegendRelief",
+ DEF_LINE_LABEL_RELIEF, Blt_Offset(LineElement, legendRelief),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "LineWidth",
+ DEF_LINE_PEN_WIDTH, Blt_Offset(LineElement, builtinPen.traceWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX",
+ DEF_LINE_AXIS_X, Blt_Offset(LineElement, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY",
+ DEF_LINE_AXIS_Y, Blt_Offset(LineElement, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_INT_NNEG, "-maxsymbols", "maxSymbols", "MaxSymbols",
+ DEF_LINE_MAX_SYMBOLS, Blt_Offset(LineElement, reqMaxSymbols),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash",
+ DEF_LINE_OFFDASH_COLOR,
+ Blt_Offset(LineElement, builtinPen.traceOffColor),
+ BLT_CONFIG_NULL_OK, &bltColorOption},
+ {BLT_CONFIG_CUSTOM, "-outline", "outline", "Outline",
+ DEF_LINE_OUTLINE_COLOR,
+ Blt_Offset(LineElement, builtinPen.symbol.outlineColor),
+ 0, &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-outlinewidth", "outlineWidth", "OutlineWidth",
+ DEF_LINE_OUTLINE_WIDTH,
+ Blt_Offset(LineElement, builtinPen.symbol.outlineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-pen", "pen", "Pen", (char *)NULL,
+ Blt_Offset(LineElement, normalPenPtr), BLT_CONFIG_NULL_OK,
+ &bltLinePenOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-pixels", "pixels", "Pixels", DEF_LINE_PIXELS,
+ Blt_Offset(LineElement, builtinPen.symbol.size), GRAPH | STRIPCHART},
+ {BLT_CONFIG_FLOAT, "-reduce", "reduce", "Reduce",
+ DEF_LINE_REDUCE, Blt_Offset(LineElement, rTolerance),
+ GRAPH | STRIPCHART | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-scalesymbols", "scaleSymbols", "ScaleSymbols",
+ DEF_LINE_SCALE_SYMBOLS, Blt_Offset(LineElement, scaleSymbols),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FILL, "-showerrorbars", "showErrorBars", "ShowErrorBars",
+ DEF_LINE_SHOW_ERRORBARS,
+ Blt_Offset(LineElement, builtinPen.errorBarShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FILL, "-showvalues", "showValues", "ShowValues",
+ DEF_PEN_SHOW_VALUES, Blt_Offset(LineElement, builtinPen.valueShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-smooth", "smooth", "Smooth", DEF_LINE_SMOOTH,
+ Blt_Offset(LineElement, reqSmooth), BLT_CONFIG_DONT_SET_DEFAULT,
+ &smoothOption},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_LINE_STATE,
+ Blt_Offset(LineElement, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-styles", "styles", "Styles", DEF_LINE_STYLES,
+ Blt_Offset(LineElement, styles), 0, &bltLineStylesOption},
+ {BLT_CONFIG_CUSTOM, "-symbol", "symbol", "Symbol", DEF_LINE_SYMBOL,
+ Blt_Offset(LineElement, builtinPen.symbol),
+ BLT_CONFIG_DONT_SET_DEFAULT, &symbolOption},
+ {BLT_CONFIG_CUSTOM, "-trace", "trace", "Trace", DEF_LINE_PEN_DIRECTION,
+ Blt_Offset(LineElement, penDir),
+ BLT_CONFIG_DONT_SET_DEFAULT, &penDirOption},
+ {BLT_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
+ DEF_PEN_VALUE_ANCHOR,
+ Blt_Offset(LineElement, builtinPen.valueStyle.anchor), 0},
+ {BLT_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
+ DEF_PEN_VALUE_COLOR,
+ Blt_Offset(LineElement, builtinPen.valueStyle.color), 0},
+ {BLT_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
+ DEF_PEN_VALUE_FONT,
+ Blt_Offset(LineElement, builtinPen.valueStyle.font), 0},
+ {BLT_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
+ DEF_PEN_VALUE_FORMAT, Blt_Offset(LineElement, builtinPen.valueFormat),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_FLOAT, "-valuerotate", "valueRotate", "ValueRotate",
+ DEF_PEN_VALUE_ANGLE,
+ Blt_Offset(LineElement, builtinPen.valueStyle.angle), 0},
+ {BLT_CONFIG_CUSTOM, "-weights", "weights", "Weights", (char *)NULL,
+ Blt_Offset(LineElement, w), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-x", "xData", "XData", (char *)NULL,
+ Blt_Offset(LineElement, x), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xdata", "xData", "XData", (char *)NULL,
+ Blt_Offset(LineElement, x), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xerror", "xError", "XError", (char *)NULL,
+ Blt_Offset(LineElement, xError), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xhigh", "xHigh", "XHigh", (char *)NULL,
+ Blt_Offset(LineElement, xHigh), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-xlow", "xLow", "XLow", (char *)NULL,
+ Blt_Offset(LineElement, xLow), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-y", "yData", "YData", (char *)NULL,
+ Blt_Offset(LineElement, y), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-ydata", "yData", "YData", (char *)NULL,
+ Blt_Offset(LineElement, y), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-yerror", "yError", "YError", (char *)NULL,
+ Blt_Offset(LineElement, yError), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-yhigh", "yHigh", "YHigh", (char *)NULL,
+ Blt_Offset(LineElement, yHigh), 0, &bltValuesOption},
+ {BLT_CONFIG_CUSTOM, "-ylow", "yLow", "YLow", (char *)NULL,
+ Blt_Offset(LineElement, yLow), 0, &bltValuesOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+
+static Blt_ConfigSpec linePenConfigSpecs[] =
+{
+ {BLT_CONFIG_COLOR, "-color", "color", "Color", DEF_PEN_ACTIVE_COLOR,
+ Blt_Offset(LinePen, traceColor), ACTIVE_PEN},
+ {BLT_CONFIG_COLOR, "-color", "color", "Color", DEF_PEN_NORMAL_COLOR,
+ Blt_Offset(LinePen, traceColor), NORMAL_PEN},
+ {BLT_CONFIG_DASHES, "-dashes", "dashes", "Dashes", DEF_PEN_DASHES,
+ Blt_Offset(LinePen, traceDashes), BLT_CONFIG_NULL_OK | ALL_PENS},
+ {BLT_CONFIG_CUSTOM, "-errorbarcolor", "errorBarColor", "ErrorBarColor",
+ DEF_LINE_ERRORBAR_COLOR, Blt_Offset(LinePen, errorBarColor),
+ ALL_PENS, &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarwidth", "errorBarWidth", "ErrorBarWidth",
+ DEF_LINE_ERRORBAR_LINE_WIDTH, Blt_Offset(LinePen, errorBarLineWidth),
+ ALL_PENS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-errorbarcap", "errorBarCap", "ErrorBarCap",
+ DEF_LINE_ERRORBAR_CAP_WIDTH, Blt_Offset(LinePen, errorBarCapWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-fill", "fill", "Fill", DEF_PEN_FILL_COLOR,
+ Blt_Offset(LinePen, symbol.fillColor), BLT_CONFIG_NULL_OK | ALL_PENS,
+ &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "LineWidth",
+ (char *)NULL, Blt_Offset(LinePen, traceWidth),
+ ALL_PENS| BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-offdash", "offDash", "OffDash", DEF_PEN_OFFDASH_COLOR,
+ Blt_Offset(LinePen, traceOffColor), BLT_CONFIG_NULL_OK | ALL_PENS,
+ &bltColorOption},
+ {BLT_CONFIG_CUSTOM, "-outline", "outline", "Outline", DEF_PEN_OUTLINE_COLOR,
+ Blt_Offset(LinePen, symbol.outlineColor), ALL_PENS, &bltColorOption},
+ {BLT_CONFIG_PIXELS_NNEG, "-outlinewidth", "outlineWidth", "OutlineWidth",
+ DEF_PEN_OUTLINE_WIDTH, Blt_Offset(LinePen, symbol.outlineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT | ALL_PENS},
+ {BLT_CONFIG_PIXELS_NNEG, "-pixels", "pixels", "Pixels", DEF_PEN_PIXELS,
+ Blt_Offset(LinePen, symbol.size), ALL_PENS},
+ {BLT_CONFIG_FILL, "-showerrorbars", "showErrorBars", "ShowErrorBars",
+ DEF_LINE_SHOW_ERRORBARS, Blt_Offset(LinePen, errorBarShow),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FILL, "-showvalues", "showValues", "ShowValues",
+ DEF_PEN_SHOW_VALUES, Blt_Offset(LinePen, valueShow),
+ ALL_PENS | BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-symbol", "symbol", "Symbol", DEF_PEN_SYMBOL,
+ Blt_Offset(LinePen, symbol), BLT_CONFIG_DONT_SET_DEFAULT | ALL_PENS,
+ &symbolOption},
+ {BLT_CONFIG_STRING, "-type", (char *)NULL, (char *)NULL, DEF_PEN_TYPE,
+ Blt_Offset(Pen, typeId), ALL_PENS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_ANCHOR, "-valueanchor", "valueAnchor", "ValueAnchor",
+ DEF_PEN_VALUE_ANCHOR, Blt_Offset(LinePen, valueStyle.anchor), ALL_PENS},
+ {BLT_CONFIG_COLOR, "-valuecolor", "valueColor", "ValueColor",
+ DEF_PEN_VALUE_COLOR, Blt_Offset(LinePen, valueStyle.color), ALL_PENS},
+ {BLT_CONFIG_FONT, "-valuefont", "valueFont", "ValueFont",
+ DEF_PEN_VALUE_FONT, Blt_Offset(LinePen, valueStyle.font), ALL_PENS},
+ {BLT_CONFIG_STRING, "-valueformat", "valueFormat", "ValueFormat",
+ DEF_PEN_VALUE_FORMAT, Blt_Offset(LinePen, valueFormat),
+ ALL_PENS | BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_FLOAT, "-valuerotate", "valueRotate", "ValueRotate",
+ DEF_PEN_VALUE_ANGLE, Blt_Offset(LinePen, valueStyle.angle), ALL_PENS},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+typedef double (DistanceProc)(int x, int y, Point2d *p, Point2d *q, Point2d *t);
+
+/* Forward declarations */
+static PenConfigureProc ConfigurePenProc;
+static PenDestroyProc DestroyPenProc;
+static ElementClosestProc ClosestLineProc;
+static ElementConfigProc ConfigureLineProc;
+static ElementDestroyProc DestroyLineProc;
+static ElementDrawProc DrawActiveLineProc;
+static ElementDrawProc DrawNormalLineProc;
+static ElementDrawSymbolProc DrawSymbolProc;
+static ElementExtentsProc GetLineExtentsProc;
+static ElementToPostScriptProc ActiveLineToPostScriptProc;
+static ElementToPostScriptProc NormalLineToPostScriptProc;
+static ElementSymbolToPostScriptProc SymbolToPostScriptProc;
+static ElementMapProc MapLineProc;
+static DistanceProc DistanceToYProc;
+static DistanceProc DistanceToXProc;
+static DistanceProc DistanceToLineProc;
+static Blt_BackgroundChangedProc BackgroundChangedProc;
+
+INLINE static int
+Round(double x)
+{
+ return (int) (x + ((x < 0.0) ? -0.5 : 0.5));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * Custom configuration option (parse and print) routines
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DestroySymbol(Display *display, Symbol *symbolPtr)
+{
+ if (symbolPtr->image != NULL) {
+ Tk_FreeImage(symbolPtr->image);
+ symbolPtr->image = NULL;
+ }
+ if (symbolPtr->bitmap != None) {
+ Tk_FreeBitmap(display, symbolPtr->bitmap);
+ symbolPtr->bitmap = None;
+ }
+ if (symbolPtr->mask != None) {
+ Tk_FreeBitmap(display, symbolPtr->mask);
+ symbolPtr->mask = None;
+ }
+ symbolPtr->type = SYMBOL_NONE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ImageChangedProc
+ *
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+ImageChangedProc(
+ ClientData clientData,
+ int x, int y, int w, int h, /* Not used. */
+ int imageWidth, int imageHeight) /* Not used. */
+{
+ Element *elemPtr;
+ Graph *graphPtr;
+
+ elemPtr = clientData;
+ elemPtr->flags |= MAP_ITEM;
+ graphPtr = elemPtr->obj.graphPtr;
+ graphPtr->flags |= CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+}
+
+/*ARGSUSED*/
+static void
+FreeSymbolProc(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Symbol *symbolPtr = (Symbol *)(widgRec + offset);
+
+ DestroySymbol(display, symbolPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToSymbol --
+ *
+ * Convert the string representation of a line style or symbol name into
+ * its numeric form.
+ *
+ * Results:
+ * The return value is a standard TCL result. The symbol type is written
+ * into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToSymbolProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing symbol type */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Symbol *symbolPtr = (Symbol *)(widgRec + offset);
+ const char *string;
+
+ {
+ int length;
+ GraphSymbolType *p;
+ char c;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ if (length == 0) {
+ DestroySymbol(Tk_Display(tkwin), symbolPtr);
+ symbolPtr->type = SYMBOL_NONE;
+ return TCL_OK;
+ }
+ c = string[0];
+ for (p = graphSymbols; p->name != NULL; p++) {
+ if (length < p->minChars) {
+ continue;
+ }
+ if ((c == p->name[0]) && (strncmp(string, p->name, length) == 0)) {
+ DestroySymbol(Tk_Display(tkwin), symbolPtr);
+ symbolPtr->type = p->type;
+ return TCL_OK;
+ }
+ }
+ }
+ {
+ Tk_Image tkImage;
+ Element *elemPtr = (Element *)widgRec;
+
+ tkImage = Tk_GetImage(interp, tkwin, string, ImageChangedProc, elemPtr);
+ if (tkImage != NULL) {
+ DestroySymbol(Tk_Display(tkwin), symbolPtr);
+ symbolPtr->image = tkImage;
+ symbolPtr->type = SYMBOL_IMAGE;
+ return TCL_OK;
+ }
+ }
+ {
+ Pixmap bitmap, mask;
+ Tcl_Obj **objv;
+ int objc;
+
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) ||
+ (objc > 2)) {
+ goto error;
+ }
+ bitmap = mask = None;
+ if (objc > 0) {
+ bitmap = Tk_AllocBitmapFromObj((Tcl_Interp *)NULL, tkwin, objv[0]);
+ if (bitmap == None) {
+ goto error;
+ }
+ }
+ if (objc > 1) {
+ mask = Tk_AllocBitmapFromObj((Tcl_Interp *)NULL, tkwin, objv[1]);
+ if (mask == None) {
+ goto error;
+ }
+ }
+ DestroySymbol(Tk_Display(tkwin), symbolPtr);
+ symbolPtr->bitmap = bitmap;
+ symbolPtr->mask = mask;
+ symbolPtr->type = SYMBOL_BITMAP;
+ return TCL_OK;
+ }
+ error:
+ Tcl_AppendResult(interp, "bad symbol \"", string,
+ "\": should be \"none\", \"circle\", \"square\", \"diamond\", "
+ "\"plus\", \"cross\", \"splus\", \"scross\", \"triangle\", "
+ "\"arrow\" or the name of a bitmap", (char *)NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SymbolToObj --
+ *
+ * Convert the symbol value into a string.
+ *
+ * Results:
+ * The string representing the symbol type or line style is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+SymbolToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Symbol *symbolPtr = (Symbol *)(widgRec + offset);
+
+ if (symbolPtr->type == SYMBOL_BITMAP) {
+ Tcl_Obj *listObjPtr, *objPtr;
+ const char *name;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ name = Tk_NameOfBitmap(Tk_Display(tkwin), symbolPtr->bitmap);
+ objPtr = Tcl_NewStringObj(name, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ if (symbolPtr->mask == None) {
+ objPtr = Tcl_NewStringObj("", -1);
+ } else {
+ name = Tk_NameOfBitmap(Tk_Display(tkwin), symbolPtr->mask);
+ objPtr = Tcl_NewStringObj(name, -1);
+ }
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ return listObjPtr;
+ } else {
+ GraphSymbolType *p;
+
+ for (p = graphSymbols; p->name != NULL; p++) {
+ if (p->type == symbolPtr->type) {
+ return Tcl_NewStringObj(p->name, -1);
+ }
+ }
+ return Tcl_NewStringObj("?unknown symbol type?", -1);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NameOfSmooth --
+ *
+ * Converts the smooth value into its string representation.
+ *
+ * Results:
+ * The static string representing the smooth type is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static const char *
+NameOfSmooth(Smoothing value)
+{
+ SmoothingInfo *siPtr;
+
+ for (siPtr = smoothingInfo; siPtr->name != NULL; siPtr++) {
+ if (siPtr->value == value) {
+ return siPtr->name;
+ }
+ }
+ return "unknown smooth value";
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToSmooth --
+ *
+ * Convert the string representation of a line style or smooth name
+ * into its numeric form.
+ *
+ * Results:
+ * The return value is a standard TCL result. The smooth type is
+ * written into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToSmoothProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing smooth type */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Smoothing *valuePtr = (Smoothing *)(widgRec + offset);
+ SmoothingInfo *siPtr;
+ const char *string;
+ char c;
+
+ string = Tcl_GetString(objPtr);
+ c = string[0];
+ for (siPtr = smoothingInfo; siPtr->name != NULL; siPtr++) {
+ if ((c == siPtr->name[0]) && (strcmp(string, siPtr->name) == 0)) {
+ *valuePtr = siPtr->value;
+ return TCL_OK;
+ }
+ }
+ Tcl_AppendResult(interp, "bad smooth value \"", string, "\": should be \
+linear, step, natural, or quadratic", (char *)NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SmoothToObj --
+ *
+ * Convert the smooth value into a string.
+ *
+ * Results:
+ * The string representing the smooth type or line style is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+SmoothToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int smooth = *(int *)(widgRec + offset);
+
+ return Tcl_NewStringObj(NameOfSmooth(smooth), -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPenDir --
+ *
+ * Convert the string representation of a line style or symbol name
+ * into its numeric form.
+ *
+ * Results:
+ * The return value is a standard TCL result. The symbol type is
+ * written into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPenDirProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing pen direction */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int *penDirPtr = (int *)(widgRec + offset);
+ int length;
+ char c;
+ char *string;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'i') && (strncmp(string, "increasing", length) == 0)) {
+ *penDirPtr = PEN_INCREASING;
+ } else if ((c == 'd') && (strncmp(string, "decreasing", length) == 0)) {
+ *penDirPtr = PEN_DECREASING;
+ } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
+ *penDirPtr = PEN_BOTH_DIRECTIONS;
+ } else {
+ Tcl_AppendResult(interp, "bad trace value \"", string,
+ "\" : should be \"increasing\", \"decreasing\", or \"both\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NameOfPenDir --
+ *
+ * Convert the pen direction into a string.
+ *
+ * Results:
+ * The static string representing the pen direction is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static const char *
+NameOfPenDir(int penDir)
+{
+ switch (penDir) {
+ case PEN_INCREASING:
+ return "increasing";
+ case PEN_DECREASING:
+ return "decreasing";
+ case PEN_BOTH_DIRECTIONS:
+ return "both";
+ default:
+ return "unknown trace direction";
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PenDirToObj --
+ *
+ * Convert the pen direction into a string.
+ *
+ * Results:
+ * The string representing the pen drawing direction is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PenDirToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int penDir = *(int *)(widgRec + offset);
+
+ return Tcl_NewStringObj(NameOfPenDir(penDir), -1);
+}
+
+
+/*
+ * Reset the number of points and segments, in case there are no segments or
+ * points
+ */
+static void
+ResetStylePalette(Blt_Chain styles)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(styles); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->lines.length = stylePtr->symbolPts.length = 0;
+ stylePtr->xeb.length = stylePtr->yeb.length = 0;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigurePenProc --
+ *
+ * Sets up the appropriate configuration parameters in the GC. It is
+ * assumed the parameters have been previously set by a call to
+ * Blt_ConfigureWidget.
+ *
+ * Results:
+ * The return value is a standard TCL result. If TCL_ERROR is returned,
+ * then interp->result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as line width, line style, color
+ * etc. get set in a new GC.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ConfigurePenProc(Graph *graphPtr, Pen *penPtr)
+{
+ LinePen *lpPtr = (LinePen *)penPtr;
+ unsigned long gcMask;
+ GC newGC;
+ XGCValues gcValues;
+ XColor *colorPtr;
+
+ /*
+ * Set the outline GC for this pen: GCForeground is outline color.
+ * GCBackground is the fill color (only used for bitmap symbols).
+ */
+ gcMask = (GCLineWidth | GCForeground);
+ colorPtr = lpPtr->symbol.outlineColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = lpPtr->traceColor;
+ }
+ gcValues.foreground = colorPtr->pixel;
+ if (lpPtr->symbol.type == SYMBOL_BITMAP) {
+ colorPtr = lpPtr->symbol.fillColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = lpPtr->traceColor;
+ }
+ /*
+ * Set a clip mask if either
+ * 1) no background color was designated or
+ * 2) a masking bitmap was specified.
+ *
+ * These aren't necessarily the bitmaps we'll be using for clipping. But
+ * this makes it unlikely that anyone else will be sharing this GC when
+ * we set the clip origin (at the time the bitmap is drawn).
+ */
+ if (colorPtr != NULL) {
+ gcValues.background = colorPtr->pixel;
+ gcMask |= GCBackground;
+ if (lpPtr->symbol.mask != None) {
+ gcValues.clip_mask = lpPtr->symbol.mask;
+ gcMask |= GCClipMask;
+ }
+ } else {
+ gcValues.clip_mask = lpPtr->symbol.bitmap;
+ gcMask |= GCClipMask;
+ }
+ }
+ gcValues.line_width = LineWidth(lpPtr->symbol.outlineWidth);
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (lpPtr->symbol.outlineGC != NULL) {
+ Tk_FreeGC(graphPtr->display, lpPtr->symbol.outlineGC);
+ }
+ lpPtr->symbol.outlineGC = newGC;
+
+ /* Fill GC for symbols: GCForeground is fill color */
+
+ gcMask = (GCLineWidth | GCForeground);
+ colorPtr = lpPtr->symbol.fillColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = lpPtr->traceColor;
+ }
+ newGC = NULL;
+ if (colorPtr != NULL) {
+ gcValues.foreground = colorPtr->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ }
+ if (lpPtr->symbol.fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, lpPtr->symbol.fillGC);
+ }
+ lpPtr->symbol.fillGC = newGC;
+
+ /* Line segments */
+
+ gcMask = (GCLineWidth | GCForeground | GCLineStyle | GCCapStyle |
+ GCJoinStyle);
+ gcValues.cap_style = CapButt;
+ gcValues.join_style = JoinRound;
+ gcValues.line_style = LineSolid;
+ gcValues.line_width = LineWidth(lpPtr->traceWidth);
+
+ colorPtr = lpPtr->traceOffColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = lpPtr->traceColor;
+ }
+ if (colorPtr != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = colorPtr->pixel;
+ }
+ gcValues.foreground = lpPtr->traceColor->pixel;
+ if (LineIsDashed(lpPtr->traceDashes)) {
+ gcValues.line_width = lpPtr->traceWidth;
+ gcValues.line_style =
+ (colorPtr == NULL) ? LineOnOffDash : LineDoubleDash;
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (lpPtr->traceGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, lpPtr->traceGC);
+ }
+ if (LineIsDashed(lpPtr->traceDashes)) {
+ lpPtr->traceDashes.offset = lpPtr->traceDashes.values[0] / 2;
+ Blt_SetDashes(graphPtr->display, newGC, &lpPtr->traceDashes);
+ }
+ lpPtr->traceGC = newGC;
+
+ gcMask = (GCLineWidth | GCForeground);
+ colorPtr = lpPtr->errorBarColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = lpPtr->traceColor;
+ }
+ gcValues.line_width = LineWidth(lpPtr->errorBarLineWidth);
+ gcValues.foreground = colorPtr->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (lpPtr->errorBarGC != NULL) {
+ Tk_FreeGC(graphPtr->display, lpPtr->errorBarGC);
+ }
+ lpPtr->errorBarGC = newGC;
+
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyPenProc --
+ *
+ * Release memory and resources allocated for the style.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the pen style is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DestroyPenProc(Graph *graphPtr, Pen *basePtr)
+{
+ LinePen *penPtr = (LinePen *)basePtr;
+
+ Blt_Ts_FreeStyle(graphPtr->display, &penPtr->valueStyle);
+ if (penPtr->symbol.outlineGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->symbol.outlineGC);
+ }
+ if (penPtr->symbol.fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->symbol.fillGC);
+ }
+ if (penPtr->errorBarGC != NULL) {
+ Tk_FreeGC(graphPtr->display, penPtr->errorBarGC);
+ }
+ if (penPtr->traceGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, penPtr->traceGC);
+ }
+ if (penPtr->symbol.bitmap != None) {
+ Tk_FreeBitmap(graphPtr->display, penPtr->symbol.bitmap);
+ penPtr->symbol.bitmap = None;
+ }
+ if (penPtr->symbol.mask != None) {
+ Tk_FreeBitmap(graphPtr->display, penPtr->symbol.mask);
+ penPtr->symbol.mask = None;
+ }
+}
+
+
+static void
+InitLinePen(LinePen *penPtr)
+{
+ Blt_Ts_InitStyle(penPtr->valueStyle);
+ penPtr->errorBarLineWidth = 2;
+ penPtr->errorBarShow = SHOW_BOTH;
+ penPtr->configProc = ConfigurePenProc;
+ penPtr->configSpecs = linePenConfigSpecs;
+ penPtr->destroyProc = DestroyPenProc;
+ penPtr->flags = NORMAL_PEN;
+ penPtr->name = "";
+ penPtr->symbol.bitmap = penPtr->symbol.mask = None;
+ penPtr->symbol.outlineColor = penPtr->symbol.fillColor = COLOR_DEFAULT;
+ penPtr->symbol.outlineWidth = penPtr->traceWidth = 1;
+ penPtr->symbol.type = SYMBOL_CIRCLE;
+ penPtr->valueShow = SHOW_NONE;
+}
+
+Pen *
+Blt_LinePen(const char *penName)
+{
+ LinePen *penPtr;
+
+ penPtr = calloc(1, sizeof(LinePen));
+ InitLinePen(penPtr);
+ penPtr->name = Blt_Strdup(penName);
+ penPtr->classId = CID_ELEM_LINE;
+ if (strcmp(penName, "activeLine") == 0) {
+ penPtr->flags = ACTIVE_PEN;
+ }
+ return (Pen *)penPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * In this section, the routines deal with building and filling the
+ * element's data structures with transformed screen coordinates. They are
+ * triggered from TranformLine which is called whenever the data or
+ * coordinates axes have changed and new screen coordinates need to be
+ * calculated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ScaleSymbol --
+ *
+ * Returns the scaled size for the line element. Scaling depends upon when
+ * the base line ranges for the element were set and the current range of
+ * the graph.
+ *
+ * Results:
+ * The new size of the symbol, after considering how much the graph has
+ * been scaled, is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ScaleSymbol(LineElement *elemPtr, int normalSize)
+{
+ int maxSize;
+ double scale;
+ int newSize;
+
+ scale = 1.0;
+ if (elemPtr->scaleSymbols) {
+ double xRange, yRange;
+
+ xRange = (elemPtr->axes.x->max - elemPtr->axes.x->min);
+ yRange = (elemPtr->axes.y->max - elemPtr->axes.y->min);
+ if (elemPtr->flags & SCALE_SYMBOL) {
+ /* Save the ranges as a baseline for future scaling. */
+ elemPtr->xRange = xRange;
+ elemPtr->yRange = yRange;
+ elemPtr->flags &= ~SCALE_SYMBOL;
+ } else {
+ double xScale, yScale;
+
+ /* Scale the symbol by the smallest change in the X or Y axes */
+ xScale = elemPtr->xRange / xRange;
+ yScale = elemPtr->yRange / yRange;
+ scale = MIN(xScale, yScale);
+ }
+ }
+ newSize = Round(normalSize * scale);
+
+ /*
+ * Don't let the size of symbols go unbounded. Both X and Win32 drawing
+ * routines assume coordinates to be a signed short int.
+ */
+ maxSize = (int)MIN(elemPtr->obj.graphPtr->hRange,
+ elemPtr->obj.graphPtr->vRange);
+ if (newSize > maxSize) {
+ newSize = maxSize;
+ }
+
+ /* Make the symbol size odd so that its center is a single pixel. */
+ newSize |= 0x01;
+ return newSize;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetScreenPoints --
+ *
+ * Generates a coordinate array of transformed screen coordinates from
+ * the data points. Coordinates with Inf, -Inf, or NaN values are
+ * removed.
+ *
+ * Results:
+ * The transformed screen coordinates are returned.
+ *
+ * Side effects:
+ * Memory is allocated for the coordinate array.
+ *
+ *
+ * Future ideas:
+ * Allow bad values to be removed (as done currently) or break
+ * into separate traces. Smoothing would be affected.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GetScreenPoints(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ double *x, *y;
+ int i, np;
+ int count;
+ Point2d *points;
+ int *map;
+
+ np = NUMBEROFPOINTS(elemPtr);
+ x = elemPtr->x.values;
+ y = elemPtr->y.values;
+ points = malloc(sizeof(Point2d) * np);
+ map = malloc(sizeof(int) * np);
+
+ count = 0; /* Count the valid screen coordinates */
+ if (graphPtr->inverted) {
+ for (i = 0; i < np; i++) {
+ if ((isfinite(x[i])) && (isfinite(y[i]))) {
+ points[count].x = Blt_HMap(elemPtr->axes.y, y[i]);
+ points[count].y = Blt_VMap(elemPtr->axes.x, x[i]);
+ map[count] = i;
+ count++;
+ }
+ }
+ } else {
+ for (i = 0; i < np; i++) {
+ if ((isfinite(x[i])) && (isfinite(y[i]))) {
+ points[count].x = Blt_HMap(elemPtr->axes.x, x[i]);
+ points[count].y = Blt_VMap(elemPtr->axes.y, y[i]);
+ map[count] = i;
+ count++;
+ }
+ }
+ }
+ mapPtr->screenPts = points;
+ mapPtr->nScreenPts = count;
+ mapPtr->map = map;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ReducePoints --
+ *
+ * Generates a coordinate array of transformed screen coordinates from
+ * the data points.
+ *
+ * Results:
+ * The transformed screen coordinates are returned.
+ *
+ * Side effects:
+ * Memory is allocated for the coordinate array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ReducePoints(MapInfo *mapPtr, double tolerance)
+{
+ int i, np;
+ Point2d *screenPts;
+ int *map, *simple;
+
+ simple = malloc(mapPtr->nScreenPts * sizeof(int));
+ map = malloc(mapPtr->nScreenPts * sizeof(int));
+ screenPts = malloc(mapPtr->nScreenPts * sizeof(Point2d));
+ np = Blt_SimplifyLine(mapPtr->screenPts, 0, mapPtr->nScreenPts - 1,
+ tolerance, simple);
+ for (i = 0; i < np; i++) {
+ int k;
+
+ k = simple[i];
+ screenPts[i] = mapPtr->screenPts[k];
+ map[i] = mapPtr->map[k];
+ }
+ free(mapPtr->screenPts);
+ free(mapPtr->map);
+ free(simple);
+ mapPtr->screenPts = screenPts;
+ mapPtr->map = map;
+ mapPtr->nScreenPts = np;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GenerateSteps --
+ *
+ * Resets the coordinate and pen index arrays adding new points for
+ * step-and-hold type smoothing.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The temporary arrays for screen coordinates and pen indices
+ * are updated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GenerateSteps(MapInfo *mapPtr)
+{
+ int newSize;
+ int i, count;
+ Point2d *screenPts;
+ int *map;
+
+ newSize = ((mapPtr->nScreenPts - 1) * 2) + 1;
+ screenPts = malloc(newSize * sizeof(Point2d));
+ map = malloc(sizeof(int) * newSize);
+ screenPts[0] = mapPtr->screenPts[0];
+ map[0] = 0;
+
+ count = 1;
+ for (i = 1; i < mapPtr->nScreenPts; i++) {
+ screenPts[count + 1] = mapPtr->screenPts[i];
+
+ /* Hold last y-coordinate, use new x-coordinate */
+ screenPts[count].x = screenPts[count + 1].x;
+ screenPts[count].y = screenPts[count - 1].y;
+
+ /* Use the same style for both the hold and the step points */
+ map[count] = map[count + 1] = mapPtr->map[i];
+ count += 2;
+ }
+ free(mapPtr->screenPts);
+ free(mapPtr->map);
+ mapPtr->map = map;
+ mapPtr->screenPts = screenPts;
+ mapPtr->nScreenPts = newSize;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GenerateSpline --
+ *
+ * Computes a spline based upon the data points, returning a new (larger)
+ * coordinate array or points.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The temporary arrays for screen coordinates and data map are updated
+ * based upon spline.
+ *
+ * FIXME: Can't interpolate knots along the Y-axis. Need to break
+ * up point array into interchangable X and Y vectors earlier.
+ * Pass extents (left/right or top/bottom) as parameters.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GenerateSpline(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ Point2d *origPts, *iPts;
+ int *map;
+ int extra;
+ int niPts, nOrigPts;
+ int result;
+ int i, j, count;
+
+ nOrigPts = mapPtr->nScreenPts;
+ origPts = mapPtr->screenPts;
+ assert(mapPtr->nScreenPts > 0);
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+ if (origPts[j].x <= origPts[i].x) {
+ return; /* Points are not monotonically
+ * increasing */
+ }
+ }
+ if (((origPts[0].x > (double)graphPtr->right)) ||
+ ((origPts[mapPtr->nScreenPts - 1].x < (double)graphPtr->left))) {
+ return; /* All points are clipped */
+ }
+
+ /*
+ * The spline is computed in screen coordinates instead of data points so
+ * that we can select the abscissas of the interpolated points from each
+ * pixel horizontally across the plotting area.
+ */
+ extra = (graphPtr->right - graphPtr->left) + 1;
+ if (extra < 1) {
+ return;
+ }
+ niPts = nOrigPts + extra + 1;
+ iPts = malloc(niPts * sizeof(Point2d));
+ map = malloc(sizeof(int) * niPts);
+ /* Populate the x2 array with both the original X-coordinates and extra
+ * X-coordinates for each horizontal pixel that the line segment
+ * contains. */
+ count = 0;
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+
+ /* Add the original x-coordinate */
+ iPts[count].x = origPts[i].x;
+
+ /* Include the starting offset of the point in the offset array */
+ map[count] = mapPtr->map[i];
+ count++;
+
+ /* Is any part of the interval (line segment) in the plotting area? */
+ if ((origPts[j].x >= (double)graphPtr->left) ||
+ (origPts[i].x <= (double)graphPtr->right)) {
+ double x, last;
+
+ x = origPts[i].x + 1.0;
+
+ /*
+ * Since the line segment may be partially clipped on the left or
+ * right side, the points to interpolate are always interior to
+ * the plotting area.
+ *
+ * left right
+ * x1----|---------------------------|---x2
+ *
+ * Pick the max of the starting X-coordinate and the left edge and
+ * the min of the last X-coordinate and the right edge.
+ */
+ x = MAX(x, (double)graphPtr->left);
+ last = MIN(origPts[j].x, (double)graphPtr->right);
+
+ /* Add the extra x-coordinates to the interval. */
+ while (x < last) {
+ map[count] = mapPtr->map[i];
+ iPts[count++].x = x;
+ x++;
+ }
+ }
+ }
+ niPts = count;
+ result = FALSE;
+ if (elemPtr->smooth == PEN_SMOOTH_NATURAL) {
+ result = Blt_NaturalSpline(origPts, nOrigPts, iPts, niPts);
+ } else if (elemPtr->smooth == PEN_SMOOTH_QUADRATIC) {
+ result = Blt_QuadraticSpline(origPts, nOrigPts, iPts, niPts);
+ }
+ if (!result) {
+ /* The spline interpolation failed. We'll fallback to the current
+ * coordinates and do no smoothing (standard line segments). */
+ elemPtr->smooth = PEN_SMOOTH_LINEAR;
+ free(iPts);
+ free(map);
+ } else {
+ free(mapPtr->screenPts);
+ free(mapPtr->map);
+ mapPtr->map = map;
+ mapPtr->screenPts = iPts;
+ mapPtr->nScreenPts = niPts;
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GenerateParametricSpline --
+ *
+ * Computes a spline based upon the data points, returning a new (larger)
+ * coordinate array or points.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The temporary arrays for screen coordinates and data map are updated
+ * based upon spline.
+ *
+ * FIXME: Can't interpolate knots along the Y-axis. Need to break
+ * up point array into interchangable X and Y vectors earlier.
+ * Pass extents (left/right or top/bottom) as parameters.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GenerateParametricSpline(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ Region2d exts;
+ Point2d *origPts, *iPts;
+ int *map;
+ int niPts, nOrigPts;
+ int result;
+ int i, j, count;
+
+ nOrigPts = mapPtr->nScreenPts;
+ origPts = mapPtr->screenPts;
+ assert(mapPtr->nScreenPts > 0);
+
+ Blt_GraphExtents(graphPtr, &exts);
+
+ /*
+ * Populate the x2 array with both the original X-coordinates and extra
+ * X-coordinates for each horizontal pixel that the line segment contains.
+ */
+ count = 1;
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+ Point2d p, q;
+
+ p = origPts[i];
+ q = origPts[j];
+ count++;
+ if (Blt_LineRectClip(&exts, &p, &q)) {
+ count += (int)(hypot(q.x - p.x, q.y - p.y) * 0.5);
+ }
+ }
+ niPts = count;
+ iPts = malloc(niPts * sizeof(Point2d));
+ map = malloc(sizeof(int) * niPts);
+
+ /*
+ * FIXME: This is just plain wrong. The spline should be computed
+ * and evaluated in separate steps. This will mean breaking
+ * up this routine since the catrom coefficients can be
+ * independently computed for original data point. This
+ * also handles the problem of allocating enough points
+ * since evaluation is independent of the number of points
+ * to be evalualted. The interpolated
+ * line segments should be clipped, not the original segments.
+ */
+ count = 0;
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+ Point2d p, q;
+ double d;
+
+ p = origPts[i];
+ q = origPts[j];
+
+ d = hypot(q.x - p.x, q.y - p.y);
+ /* Add the original x-coordinate */
+ iPts[count].x = (double)i;
+ iPts[count].y = 0.0;
+
+ /* Include the starting offset of the point in the offset array */
+ map[count] = mapPtr->map[i];
+ count++;
+
+ /* Is any part of the interval (line segment) in the plotting
+ * area? */
+
+ if (Blt_LineRectClip(&exts, &p, &q)) {
+ double dp, dq;
+
+ /* Distance of original point to p. */
+ dp = hypot(p.x - origPts[i].x, p.y - origPts[i].y);
+ /* Distance of original point to q. */
+ dq = hypot(q.x - origPts[i].x, q.y - origPts[i].y);
+ dp += 2.0;
+ while(dp <= dq) {
+ /* Point is indicated by its interval and parameter t. */
+ iPts[count].x = (double)i;
+ iPts[count].y = dp / d;
+ map[count] = mapPtr->map[i];
+ count++;
+ dp += 2.0;
+ }
+ }
+ }
+ iPts[count].x = (double)i;
+ iPts[count].y = 0.0;
+ map[count] = mapPtr->map[i];
+ count++;
+ niPts = count;
+ result = FALSE;
+ if (elemPtr->smooth == PEN_SMOOTH_NATURAL) {
+ result = Blt_NaturalParametricSpline(origPts, nOrigPts, &exts, FALSE,
+ iPts, niPts);
+ } else if (elemPtr->smooth == PEN_SMOOTH_CATROM) {
+ result = Blt_CatromParametricSpline(origPts, nOrigPts, iPts, niPts);
+ }
+ if (!result) {
+ /* The spline interpolation failed. We will fall back to the current
+ * coordinates and do no smoothing (standard line segments). */
+ elemPtr->smooth = PEN_SMOOTH_LINEAR;
+ free(iPts);
+ free(map);
+ } else {
+ free(mapPtr->screenPts);
+ free(mapPtr->map);
+ mapPtr->map = map;
+ mapPtr->screenPts = iPts;
+ mapPtr->nScreenPts = niPts;
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapSymbols --
+ *
+ * Creates two arrays of points and pen map, filled with the screen
+ * coordinates of the visible
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the index array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapSymbols(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ Region2d exts;
+ Point2d *pp, *points;
+ int *map;
+ int i, count;
+
+ points = malloc(sizeof(Point2d) * mapPtr->nScreenPts);
+ map = malloc(sizeof(int) * mapPtr->nScreenPts);
+
+ Blt_GraphExtents(graphPtr, &exts);
+ count = 0; /* Count the number of visible points */
+
+ for (pp = mapPtr->screenPts, i = 0; i < mapPtr->nScreenPts; i++, pp++) {
+ if (PointInRegion(&exts, pp->x, pp->y)) {
+ points[count].x = pp->x;
+ points[count].y = pp->y;
+ map[count] = mapPtr->map[i];
+ count++;
+ }
+ }
+ elemPtr->symbolPts.points = points;
+ elemPtr->symbolPts.length = count;
+ elemPtr->symbolPts.map = map;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapActiveSymbols --
+ *
+ * Creates an array of points of the active graph coordinates.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the active point array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapActiveSymbols(Graph *graphPtr, LineElement *elemPtr)
+{
+ Point2d *points;
+ Region2d exts;
+ int *map;
+ int count, i, np;
+
+ if (elemPtr->activePts.points != NULL) {
+ free(elemPtr->activePts.points);
+ elemPtr->activePts.points = NULL;
+ }
+ if (elemPtr->activePts.map != NULL) {
+ free(elemPtr->activePts.map);
+ elemPtr->activePts.map = NULL;
+ }
+ Blt_GraphExtents(graphPtr, &exts);
+ points = malloc(sizeof(Point2d) * elemPtr->nActiveIndices);
+ map = malloc(sizeof(int) * elemPtr->nActiveIndices);
+ np = NUMBEROFPOINTS(elemPtr);
+ count = 0; /* Count the visible active points */
+ for (i = 0; i < elemPtr->nActiveIndices; i++) {
+ double x, y;
+ int iPoint;
+
+ iPoint = elemPtr->activeIndices[i];
+ if (iPoint >= np) {
+ continue; /* Index not available */
+ }
+ x = elemPtr->x.values[iPoint];
+ y = elemPtr->y.values[iPoint];
+ points[count] = Blt_Map2D(graphPtr, x, y, &elemPtr->axes);
+ map[count] = iPoint;
+ if (PointInRegion(&exts, points[count].x, points[count].y)) {
+ count++;
+ }
+ }
+ if (count > 0) {
+ elemPtr->activePts.points = points;
+ elemPtr->activePts.map = map;
+ } else {
+ /* No active points were visible. */
+ free(points);
+ free(map);
+ }
+ elemPtr->activePts.length = count;
+ elemPtr->flags &= ~ACTIVE_PENDING;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MergePens --
+ *
+ * Reorders the both arrays of points and segments to merge pens.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The old arrays are freed and new ones allocated containing
+ * the reordered points and segments.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MergePens(LineElement *elemPtr, LineStyle **styleMap)
+{
+ if (Blt_Chain_GetLength(elemPtr->styles) < 2) {
+ Blt_ChainLink link;
+ LineStyle *stylePtr;
+
+ link = Blt_Chain_FirstLink(elemPtr->styles);
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->errorBarCapWidth = elemPtr->errorBarCapWidth;
+ stylePtr->lines.length = elemPtr->lines.length;
+ stylePtr->lines.segments = elemPtr->lines.segments;
+ stylePtr->symbolPts.length = elemPtr->symbolPts.length;
+ stylePtr->symbolPts.points = elemPtr->symbolPts.points;
+ stylePtr->xeb.length = elemPtr->xeb.length;
+ stylePtr->xeb.segments = elemPtr->xeb.segments;
+ stylePtr->yeb.length = elemPtr->yeb.length;
+ stylePtr->yeb.segments = elemPtr->yeb.segments;
+ return;
+ }
+
+ /* We have more than one style. Group line segments and points of like pen
+ * styles. */
+ if (elemPtr->lines.length > 0) {
+ Blt_ChainLink link;
+ Segment2d *sp, *segments;
+ int *ip;
+ int *map;
+
+ segments = malloc(elemPtr->lines.length * sizeof(Segment2d));
+ map = malloc(elemPtr->lines.length * sizeof(int));
+ sp = segments, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->lines.segments = sp;
+ for (i = 0; i < elemPtr->lines.length; i++) {
+ int iData;
+
+ iData = elemPtr->lines.map[i];
+ if (styleMap[iData] == stylePtr) {
+ *sp++ = elemPtr->lines.segments[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->lines.length = sp - stylePtr->lines.segments;
+ }
+ free(elemPtr->lines.segments);
+ elemPtr->lines.segments = segments;
+ free(elemPtr->lines.map);
+ elemPtr->lines.map = map;
+ }
+ if (elemPtr->symbolPts.length > 0) {
+ Blt_ChainLink link;
+ int *ip;
+ Point2d *points, *pp;
+ int *map;
+
+ points = malloc(elemPtr->symbolPts.length * sizeof(Point2d));
+ map = malloc(elemPtr->symbolPts.length * sizeof(int));
+ pp = points, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->symbolPts.points = pp;
+ for (i = 0; i < elemPtr->symbolPts.length; i++) {
+ int iData;
+
+ iData = elemPtr->symbolPts.map[i];
+ if (styleMap[iData] == stylePtr) {
+ *pp++ = elemPtr->symbolPts.points[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->symbolPts.length = pp - stylePtr->symbolPts.points;
+ }
+ free(elemPtr->symbolPts.points);
+ free(elemPtr->symbolPts.map);
+ elemPtr->symbolPts.points = points;
+ elemPtr->symbolPts.map = map;
+ }
+ if (elemPtr->xeb.length > 0) {
+ Segment2d *segments, *sp;
+ int *map, *ip;
+ Blt_ChainLink link;
+
+ segments = malloc(elemPtr->xeb.length * sizeof(Segment2d));
+ map = malloc(elemPtr->xeb.length * sizeof(int));
+ sp = segments, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->xeb.segments = sp;
+ for (i = 0; i < elemPtr->xeb.length; i++) {
+ int iData;
+
+ iData = elemPtr->xeb.map[i];
+ if (styleMap[iData] == stylePtr) {
+ *sp++ = elemPtr->xeb.segments[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->xeb.length = sp - stylePtr->xeb.segments;
+ }
+ free(elemPtr->xeb.segments);
+ free(elemPtr->xeb.map);
+ elemPtr->xeb.segments = segments;
+ elemPtr->xeb.map = map;
+ }
+ if (elemPtr->yeb.length > 0) {
+ Segment2d *segments, *sp;
+ int *map, *ip;
+ Blt_ChainLink link;
+
+ segments = malloc(elemPtr->yeb.length * sizeof(Segment2d));
+ map = malloc(elemPtr->yeb.length * sizeof(int));
+ sp = segments, ip = map;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ int i;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->yeb.segments = sp;
+ for (i = 0; i < elemPtr->yeb.length; i++) {
+ int iData;
+
+ iData = elemPtr->yeb.map[i];
+ if (styleMap[iData] == stylePtr) {
+ *sp++ = elemPtr->yeb.segments[i];
+ *ip++ = iData;
+ }
+ }
+ stylePtr->yeb.length = sp - stylePtr->yeb.segments;
+ }
+ free(elemPtr->yeb.segments);
+ elemPtr->yeb.segments = segments;
+ free(elemPtr->yeb.map);
+ elemPtr->yeb.map = map;
+ }
+}
+
+#define CLIP_TOP (1<<0)
+#define CLIP_BOTTOM (1<<1)
+#define CLIP_RIGHT (1<<2)
+#define CLIP_LEFT (1<<3)
+
+INLINE static int
+OutCode(Region2d *extsPtr, Point2d *p)
+{
+ int code;
+
+ code = 0;
+ if (p->x > extsPtr->right) {
+ code |= CLIP_RIGHT;
+ } else if (p->x < extsPtr->left) {
+ code |= CLIP_LEFT;
+ }
+ if (p->y > extsPtr->bottom) {
+ code |= CLIP_BOTTOM;
+ } else if (p->y < extsPtr->top) {
+ code |= CLIP_TOP;
+ }
+ return code;
+}
+
+static int
+ClipSegment(
+ Region2d *extsPtr,
+ int code1, int code2,
+ Point2d *p, Point2d *q)
+{
+ int inside, outside;
+
+ inside = ((code1 | code2) == 0);
+ outside = ((code1 & code2) != 0);
+
+ /*
+ * In the worst case, we'll clip the line segment against each of the four
+ * sides of the bounding rectangle.
+ */
+ while ((!outside) && (!inside)) {
+ if (code1 == 0) {
+ Point2d *tmp;
+ int code;
+
+ /* Swap pointers and out codes */
+ tmp = p, p = q, q = tmp;
+ code = code1, code1 = code2, code2 = code;
+ }
+ if (code1 & CLIP_LEFT) {
+ p->y += (q->y - p->y) *
+ (extsPtr->left - p->x) / (q->x - p->x);
+ p->x = extsPtr->left;
+ } else if (code1 & CLIP_RIGHT) {
+ p->y += (q->y - p->y) *
+ (extsPtr->right - p->x) / (q->x - p->x);
+ p->x = extsPtr->right;
+ } else if (code1 & CLIP_BOTTOM) {
+ p->x += (q->x - p->x) *
+ (extsPtr->bottom - p->y) / (q->y - p->y);
+ p->y = extsPtr->bottom;
+ } else if (code1 & CLIP_TOP) {
+ p->x += (q->x - p->x) *
+ (extsPtr->top - p->y) / (q->y - p->y);
+ p->y = extsPtr->top;
+ }
+ code1 = OutCode(extsPtr, p);
+
+ inside = ((code1 | code2) == 0);
+ outside = ((code1 & code2) != 0);
+ }
+ return (!inside);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SaveTrace --
+ *
+ * Creates a new trace and inserts it into the line's list of traces.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+SaveTrace(
+ LineElement *elemPtr,
+ int start, /* Starting index of the trace in data point
+ * array. Used to figure out closest point */
+ int length, /* Number of points forming the trace */
+ MapInfo *mapPtr)
+{
+ bltTrace *tracePtr;
+ Point2d *screenPts;
+ int *map;
+ int i, j;
+
+ tracePtr = malloc(sizeof(bltTrace));
+ screenPts = malloc(sizeof(Point2d) * length);
+ map = malloc(sizeof(int) * length);
+
+ /* Copy the screen coordinates of the trace into the point array */
+
+ if (mapPtr->map != NULL) {
+ for (i = 0, j = start; i < length; i++, j++) {
+ screenPts[i].x = mapPtr->screenPts[j].x;
+ screenPts[i].y = mapPtr->screenPts[j].y;
+ map[i] = mapPtr->map[j];
+ }
+ } else {
+ for (i = 0, j = start; i < length; i++, j++) {
+ screenPts[i].x = mapPtr->screenPts[j].x;
+ screenPts[i].y = mapPtr->screenPts[j].y;
+ map[i] = j;
+ }
+ }
+ tracePtr->screenPts.length = length;
+ tracePtr->screenPts.points = screenPts;
+ tracePtr->screenPts.map = map;
+ tracePtr->start = start;
+ if (elemPtr->traces == NULL) {
+ elemPtr->traces = Blt_Chain_Create();
+ }
+ Blt_Chain_Append(elemPtr->traces, tracePtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeTraces --
+ *
+ * Deletes all the traces for the line.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeTraces(LineElement *elemPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(elemPtr->traces); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ bltTrace *tracePtr;
+
+ tracePtr = Blt_Chain_GetValue(link);
+ free(tracePtr->screenPts.map);
+ free(tracePtr->screenPts.points);
+ free(tracePtr);
+ }
+ Blt_Chain_Destroy(elemPtr->traces);
+ elemPtr->traces = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapTraces --
+ *
+ * Creates an array of line segments of the graph coordinates.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is allocated for the line segment array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapTraces(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ Point2d *p, *q;
+ Region2d exts;
+ int code1;
+ int i;
+ int start, count;
+
+ Blt_GraphExtents(graphPtr, &exts);
+ count = 1;
+ code1 = OutCode(&exts, mapPtr->screenPts);
+ p = mapPtr->screenPts;
+ q = p + 1;
+ for (i = 1; i < mapPtr->nScreenPts; i++, p++, q++) {
+ Point2d s;
+ int code2;
+ int broken, offscreen;
+
+ s.x = s.y = 0;
+ code2 = OutCode(&exts, q);
+ if (code2 != 0) {
+ /* Save the coordinates of the last point, before clipping */
+ s = *q;
+ }
+ broken = BROKEN_TRACE(elemPtr->penDir, p->x, q->x);
+ offscreen = ClipSegment(&exts, code1, code2, p, q);
+ if (broken || offscreen) {
+
+ /*
+ * The last line segment is either totally clipped by the plotting
+ * area or the x-direction is wrong, breaking the trace. Either
+ * way, save information about the last trace (if one exists),
+ * discarding the current line segment
+ */
+
+ if (count > 1) {
+ start = i - count;
+ SaveTrace(elemPtr, start, count, mapPtr);
+ count = 1;
+ }
+ } else {
+ count++; /* Add the point to the trace. */
+ if (code2 != 0) {
+
+ /*
+ * If the last point is clipped, this means that the trace is
+ * broken after this point. Restore the original coordinate
+ * (before clipping) after saving the trace.
+ */
+
+ start = i - (count - 1);
+ SaveTrace(elemPtr, start, count, mapPtr);
+ mapPtr->screenPts[i] = s;
+ count = 1;
+ }
+ }
+ code1 = code2;
+ }
+ if (count > 1) {
+ start = i - count;
+ SaveTrace(elemPtr, start, count, mapPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapFillArea --
+ *
+ * Creates an array of points that represent a polygon that fills
+ * the area under the element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is allocated for the polygon point array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapFillArea(Graph *graphPtr, LineElement *elemPtr, MapInfo *mapPtr)
+{
+ Point2d *origPts, *clipPts;
+ Region2d exts;
+ int np;
+
+ if (elemPtr->fillPts != NULL) {
+ free(elemPtr->fillPts);
+ elemPtr->fillPts = NULL;
+ elemPtr->nFillPts = 0;
+ }
+ if (mapPtr->nScreenPts < 3) {
+ return;
+ }
+ np = mapPtr->nScreenPts + 3;
+ Blt_GraphExtents(graphPtr, &exts);
+
+ origPts = malloc(sizeof(Point2d) * np);
+ if (graphPtr->inverted) {
+ double minX;
+ int i;
+
+ minX = (double)elemPtr->axes.y->screenMin;
+ for (i = 0; i < mapPtr->nScreenPts; i++) {
+ origPts[i].x = mapPtr->screenPts[i].x + 1;
+ origPts[i].y = mapPtr->screenPts[i].y;
+ if (origPts[i].x < minX) {
+ minX = origPts[i].x;
+ }
+ }
+ /* Add edges to make (if necessary) the polygon fill to the bottom of
+ * plotting window */
+ origPts[i].x = minX;
+ origPts[i].y = origPts[i - 1].y;
+ i++;
+ origPts[i].x = minX;
+ origPts[i].y = origPts[0].y;
+ i++;
+ origPts[i] = origPts[0];
+ } else {
+ double maxY;
+ int i;
+
+ maxY = (double)elemPtr->axes.y->bottom;
+ for (i = 0; i < mapPtr->nScreenPts; i++) {
+ origPts[i].x = mapPtr->screenPts[i].x + 1;
+ origPts[i].y = mapPtr->screenPts[i].y;
+ if (origPts[i].y > maxY) {
+ maxY = origPts[i].y;
+ }
+ }
+ /* Add edges to extend the fill polygon to the bottom of plotting
+ * window */
+ origPts[i].x = origPts[i - 1].x;
+ origPts[i].y = maxY;
+ i++;
+ origPts[i].x = origPts[0].x;
+ origPts[i].y = maxY;
+ i++;
+ origPts[i] = origPts[0];
+ }
+
+ clipPts = malloc(sizeof(Point2d) * np * 3);
+ np = Blt_PolyRectClip(&exts, origPts, np - 1, clipPts);
+
+ free(origPts);
+ if (np < 3) {
+ free(clipPts);
+ } else {
+ elemPtr->fillPts = clipPts;
+ elemPtr->nFillPts = np;
+ }
+}
+
+static void
+ResetLine(LineElement *elemPtr)
+{
+ FreeTraces(elemPtr);
+ ResetStylePalette(elemPtr->styles);
+ if (elemPtr->symbolPts.points != NULL) {
+ free(elemPtr->symbolPts.points);
+ }
+ if (elemPtr->symbolPts.map != NULL) {
+ free(elemPtr->symbolPts.map);
+ }
+ if (elemPtr->lines.segments != NULL) {
+ free(elemPtr->lines.segments);
+ }
+ if (elemPtr->lines.map != NULL) {
+ free(elemPtr->lines.map);
+ }
+ if (elemPtr->activePts.points != NULL) {
+ free(elemPtr->activePts.points);
+ }
+ if (elemPtr->activePts.map != NULL) {
+ free(elemPtr->activePts.map);
+ }
+ if (elemPtr->xeb.segments != NULL) {
+ free(elemPtr->xeb.segments);
+ }
+ if (elemPtr->xeb.map != NULL) {
+ free(elemPtr->xeb.map);
+ }
+ if (elemPtr->yeb.segments != NULL) {
+ free(elemPtr->yeb.segments);
+ }
+ if (elemPtr->yeb.map != NULL) {
+ free(elemPtr->yeb.map);
+ }
+ elemPtr->xeb.segments = elemPtr->yeb.segments = elemPtr->lines.segments = NULL;
+ elemPtr->symbolPts.points = elemPtr->activePts.points = NULL;
+ elemPtr->lines.map = elemPtr->symbolPts.map = elemPtr->xeb.map =
+ elemPtr->yeb.map = elemPtr->activePts.map = NULL;
+ elemPtr->activePts.length = elemPtr->symbolPts.length =
+ elemPtr->lines.length = elemPtr->xeb.length = elemPtr->yeb.length = 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapErrorBars --
+ *
+ * Creates two arrays of points and pen indices, filled with the screen
+ * coordinates of the visible
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed and allocated for the index array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapErrorBars(Graph *graphPtr, LineElement *elemPtr, LineStyle **styleMap)
+{
+ int n, np;
+ Region2d exts;
+
+ Blt_GraphExtents(graphPtr, &exts);
+ np = NUMBEROFPOINTS(elemPtr);
+ if (elemPtr->xError.nValues > 0) {
+ n = MIN(elemPtr->xError.nValues, np);
+ } else {
+ n = MIN3(elemPtr->xHigh.nValues, elemPtr->xLow.nValues, np);
+ }
+ if (n > 0) {
+ Segment2d *errorBars;
+ Segment2d *segPtr;
+ int *errorToData;
+ int *indexPtr;
+ int i;
+
+ segPtr = errorBars = malloc(n * 3 * sizeof(Segment2d));
+ indexPtr = errorToData = malloc(n * 3 * sizeof(int));
+ for (i = 0; i < n; i++) {
+ double x, y;
+ double high, low;
+ LineStyle *stylePtr;
+
+ x = elemPtr->x.values[i];
+ y = elemPtr->y.values[i];
+ stylePtr = styleMap[i];
+ if ((isfinite(x)) && (isfinite(y))) {
+ if (elemPtr->xError.nValues > 0) {
+ high = x + elemPtr->xError.values[i];
+ low = x - elemPtr->xError.values[i];
+ } else {
+ high = elemPtr->xHigh.values[i];
+ low = elemPtr->xLow.values[i];
+ }
+ if ((isfinite(high)) && (isfinite(low))) {
+ Point2d p, q;
+
+ p = Blt_Map2D(graphPtr, high, y, &elemPtr->axes);
+ q = Blt_Map2D(graphPtr, low, y, &elemPtr->axes);
+ segPtr->p = p;
+ segPtr->q = q;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Left cap */
+ segPtr->p.x = segPtr->q.x = p.x;
+ segPtr->p.y = p.y - stylePtr->errorBarCapWidth;
+ segPtr->q.y = p.y + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Right cap */
+ segPtr->p.x = segPtr->q.x = q.x;
+ segPtr->p.y = q.y - stylePtr->errorBarCapWidth;
+ segPtr->q.y = q.y + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ }
+ }
+ }
+ elemPtr->xeb.segments = errorBars;
+ elemPtr->xeb.length = segPtr - errorBars;
+ elemPtr->xeb.map = errorToData;
+ }
+ if (elemPtr->yError.nValues > 0) {
+ n = MIN(elemPtr->yError.nValues, np);
+ } else {
+ n = MIN3(elemPtr->yHigh.nValues, elemPtr->yLow.nValues, np);
+ }
+ if (n > 0) {
+ Segment2d *errorBars;
+ Segment2d *segPtr;
+ int *errorToData;
+ int *indexPtr;
+ int i;
+
+ segPtr = errorBars = malloc(n * 3 * sizeof(Segment2d));
+ indexPtr = errorToData = malloc(n * 3 * sizeof(int));
+ for (i = 0; i < n; i++) {
+ double x, y;
+ double high, low;
+ LineStyle *stylePtr;
+
+ x = elemPtr->x.values[i];
+ y = elemPtr->y.values[i];
+ stylePtr = styleMap[i];
+ if ((isfinite(x)) && (isfinite(y))) {
+ if (elemPtr->yError.nValues > 0) {
+ high = y + elemPtr->yError.values[i];
+ low = y - elemPtr->yError.values[i];
+ } else {
+ high = elemPtr->yHigh.values[i];
+ low = elemPtr->yLow.values[i];
+ }
+ if ((isfinite(high)) && (isfinite(low))) {
+ Point2d p, q;
+
+ p = Blt_Map2D(graphPtr, x, high, &elemPtr->axes);
+ q = Blt_Map2D(graphPtr, x, low, &elemPtr->axes);
+ segPtr->p = p;
+ segPtr->q = q;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Top cap. */
+ segPtr->p.y = segPtr->q.y = p.y;
+ segPtr->p.x = p.x - stylePtr->errorBarCapWidth;
+ segPtr->q.x = p.x + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ /* Bottom cap. */
+ segPtr->p.y = segPtr->q.y = q.y;
+ segPtr->p.x = q.x - stylePtr->errorBarCapWidth;
+ segPtr->q.x = q.x + stylePtr->errorBarCapWidth;
+ if (Blt_LineRectClip(&exts, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ *indexPtr++ = i;
+ }
+ }
+ }
+ }
+ elemPtr->yeb.segments = errorBars;
+ elemPtr->yeb.length = segPtr - errorBars;
+ elemPtr->yeb.map = errorToData;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapLineProc --
+ *
+ * Calculates the actual window coordinates of the line element. The
+ * window coordinates are saved in an allocated point array.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is (re)allocated for the point array.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapLineProc(Graph *graphPtr, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ MapInfo mi;
+ int size, np;
+ LineStyle **styleMap;
+ Blt_ChainLink link;
+
+ ResetLine(elemPtr);
+ np = NUMBEROFPOINTS(elemPtr);
+ if (np < 1) {
+ return; /* No data points */
+ }
+ GetScreenPoints(graphPtr, elemPtr, &mi);
+ MapSymbols(graphPtr, elemPtr, &mi);
+
+ if ((elemPtr->flags & ACTIVE_PENDING) && (elemPtr->nActiveIndices > 0)) {
+ MapActiveSymbols(graphPtr, elemPtr);
+ }
+ /*
+ * Map connecting line segments if they are to be displayed.
+ */
+ elemPtr->smooth = elemPtr->reqSmooth;
+ if ((np > 1) && (elemPtr->builtinPen.traceWidth > 0)) {
+ /*
+ * Do smoothing if necessary. This can extend the coordinate array,
+ * so both mi.points and mi.nPoints may change.
+ */
+ switch (elemPtr->smooth) {
+ case PEN_SMOOTH_STEP:
+ GenerateSteps(&mi);
+ break;
+
+ case PEN_SMOOTH_NATURAL:
+ case PEN_SMOOTH_QUADRATIC:
+ if (mi.nScreenPts < 3) {
+ /* Can't interpolate with less than three points. */
+ elemPtr->smooth = PEN_SMOOTH_LINEAR;
+ } else {
+ GenerateSpline(graphPtr, elemPtr, &mi);
+ }
+ break;
+
+ case PEN_SMOOTH_CATROM:
+ if (mi.nScreenPts < 3) {
+ /* Can't interpolate with less than three points. */
+ elemPtr->smooth = PEN_SMOOTH_LINEAR;
+ } else {
+ GenerateParametricSpline(graphPtr, elemPtr, &mi);
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (elemPtr->rTolerance > 0.0) {
+ ReducePoints(&mi, elemPtr->rTolerance);
+ }
+ if (elemPtr->fillBg != NULL) {
+ MapFillArea(graphPtr, elemPtr, &mi);
+ }
+ MapTraces(graphPtr, elemPtr, &mi);
+ }
+ free(mi.screenPts);
+ free(mi.map);
+
+ /* Set the symbol size of all the pen styles. */
+ for (link = Blt_Chain_FirstLink(elemPtr->styles); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ LinePen *penPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = (LinePen *)stylePtr->penPtr;
+ size = ScaleSymbol(elemPtr, penPtr->symbol.size);
+ stylePtr->symbolSize = size;
+ stylePtr->errorBarCapWidth = (penPtr->errorBarCapWidth > 0)
+ ? penPtr->errorBarCapWidth : Round(size * 0.6666666);
+ stylePtr->errorBarCapWidth /= 2;
+ }
+ styleMap = (LineStyle **)Blt_StyleMap((Element *)elemPtr);
+ if (((elemPtr->yHigh.nValues > 0) && (elemPtr->yLow.nValues > 0)) ||
+ ((elemPtr->xHigh.nValues > 0) && (elemPtr->xLow.nValues > 0)) ||
+ (elemPtr->xError.nValues > 0) || (elemPtr->yError.nValues > 0)) {
+ MapErrorBars(graphPtr, elemPtr, styleMap);
+ }
+ MergePens(elemPtr, styleMap);
+ free(styleMap);
+}
+
+static double
+DistanceToLineProc(
+ int x, int y, /* Sample X-Y coordinate. */
+ Point2d *p, Point2d *q, /* End points of the line segment. */
+ Point2d *t) /* (out) Point on line segment. */
+{
+ double right, left, top, bottom;
+
+ *t = Blt_GetProjection(x, y, p, q);
+ if (p->x > q->x) {
+ right = p->x, left = q->x;
+ } else {
+ left = p->x, right = q->x;
+ }
+ if (p->y > q->y) {
+ bottom = p->y, top = q->y;
+ } else {
+ top = p->y, bottom = q->y;
+ }
+ if (t->x > right) {
+ t->x = right;
+ } else if (t->x < left) {
+ t->x = left;
+ }
+ if (t->y > bottom) {
+ t->y = bottom;
+ } else if (t->y < top) {
+ t->y = top;
+ }
+ return hypot((t->x - x), (t->y - y));
+}
+
+static double
+DistanceToXProc(
+ int x, int y, /* Search X-Y coordinate. */
+ Point2d *p,
+ Point2d *q, /* End points of the line segment. */
+ Point2d *t) /* (out) Point on line segment. */
+{
+ double dx, dy;
+ double d;
+
+ if (p->x > q->x) {
+ if ((x > p->x) || (x < q->x)) {
+ return DBL_MAX; /* X-coordinate outside line segment. */
+ }
+ } else {
+ if ((x > q->x) || (x < p->x)) {
+ return DBL_MAX; /* X-coordinate outside line segment. */
+ }
+ }
+ dx = p->x - q->x;
+ dy = p->y - q->y;
+ t->x = (double)x;
+ if (fabs(dx) < DBL_EPSILON) {
+ double d1, d2;
+ /*
+ * Same X-coordinate indicates a vertical line. Pick the closest end
+ * point.
+ */
+ d1 = p->y - y;
+ d2 = q->y - y;
+ if (fabs(d1) < fabs(d2)) {
+ t->y = p->y, d = d1;
+ } else {
+ t->y = q->y, d = d2;
+ }
+ } else if (fabs(dy) < DBL_EPSILON) {
+ /* Horizontal line. */
+ t->y = p->y, d = p->y - y;
+ } else {
+ double m, b;
+
+ m = dy / dx;
+ b = p->y - (m * p->x);
+ t->y = (x * m) + b;
+ d = y - t->y;
+ }
+ return fabs(d);
+}
+
+static double
+DistanceToYProc(
+ int x, int y, /* Search X-Y coordinate. */
+ Point2d *p, Point2d *q, /* End points of the line segment. */
+ Point2d *t) /* (out) Point on line segment. */
+{
+ double dx, dy;
+ double d;
+
+ if (p->y > q->y) {
+ if ((y > p->y) || (y < q->y)) {
+ return DBL_MAX;
+ }
+ } else {
+ if ((y > q->y) || (y < p->y)) {
+ return DBL_MAX;
+ }
+ }
+ dx = p->x - q->x;
+ dy = p->y - q->y;
+ t->y = y;
+ if (fabs(dy) < DBL_EPSILON) {
+ double d1, d2;
+
+ /* Save Y-coordinate indicates an horizontal line. Pick the closest end
+ * point. */
+ d1 = p->x - x;
+ d2 = q->x - x;
+ if (fabs(d1) < fabs(d2)) {
+ t->x = p->x, d = d1;
+ } else {
+ t->x = q->x, d = d2;
+ }
+ } else if (fabs(dx) < DBL_EPSILON) {
+ /* Vertical line. */
+ t->x = p->x, d = p->x - x;
+ } else {
+ double m, b;
+
+ m = dy / dx;
+ b = p->y - (m * p->x);
+ t->x = (y - b) / m;
+ d = x - t->x;
+ }
+ return fabs(d);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClosestTrace --
+ *
+ * Find the line segment closest to the given window coordinate in the
+ * element.
+ *
+ * Results:
+ * If a new minimum distance is found, the information regarding it is
+ * returned via searchPtr.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ClosestTrace(
+ Graph *graphPtr, /* Graph widget record */
+ LineElement *elemPtr,
+ ClosestSearch *searchPtr, /* Info about closest point in
+ * element */
+ DistanceProc *distProc)
+{
+ Blt_ChainLink link;
+ Point2d closest;
+ double dMin;
+ int iClose;
+
+ iClose = -1; /* Suppress compiler warning. */
+ dMin = searchPtr->dist;
+ closest.x = closest.y = 0; /* Suppress compiler warning. */
+ for (link = Blt_Chain_FirstLink(elemPtr->traces); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ bltTrace *tracePtr;
+ Point2d *p, *pend;
+
+ tracePtr = Blt_Chain_GetValue(link);
+ for (p = tracePtr->screenPts.points,
+ pend = p + (tracePtr->screenPts.length - 1); p < pend; p++) {
+ Point2d b;
+ double d;
+
+ d = (*distProc)(searchPtr->x, searchPtr->y, p, p + 1, &b);
+ if (d < dMin) {
+ closest = b;
+ iClose = tracePtr->screenPts.map[p-tracePtr->screenPts.points];
+ dMin = d;
+ }
+ }
+ }
+ if (dMin < searchPtr->dist) {
+ searchPtr->dist = dMin;
+ searchPtr->elemPtr = (Element *)elemPtr;
+ searchPtr->index = iClose;
+ searchPtr->point = Blt_InvMap2D(graphPtr, closest.x, closest.y,
+ &elemPtr->axes);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClosestPoint --
+ *
+ * Find the element whose data point is closest to the given screen
+ * coordinate.
+ *
+ * Results:
+ * If a new minimum distance is found, the information regarding
+ * it is returned via searchPtr.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ClosestPoint(
+ LineElement *elemPtr, /* Line element to be searched. */
+ ClosestSearch *searchPtr) /* Assorted information related to
+ * searching for the closest point */
+{
+ double dMin;
+ int count, iClose;
+ Point2d *pp;
+
+ dMin = searchPtr->dist;
+ iClose = 0;
+
+ /*
+ * Instead of testing each data point in graph coordinates, look at the
+ * array of mapped screen coordinates. The advantages are
+ * 1) only examine points that are visible (unclipped), and
+ * 2) the computed distance is already in screen coordinates.
+ */
+ for (pp = elemPtr->symbolPts.points, count = 0;
+ count < elemPtr->symbolPts.length; count++, pp++) {
+ double dx, dy;
+ double d;
+
+ dx = (double)(searchPtr->x - pp->x);
+ dy = (double)(searchPtr->y - pp->y);
+ if (searchPtr->along == SEARCH_BOTH) {
+ d = hypot(dx, dy);
+ } else if (searchPtr->along == SEARCH_X) {
+ d = dx;
+ } else if (searchPtr->along == SEARCH_Y) {
+ d = dy;
+ } else {
+ /* This can't happen */
+ continue;
+ }
+ if (d < dMin) {
+ iClose = elemPtr->symbolPts.map[count];
+ dMin = d;
+ }
+ }
+ if (dMin < searchPtr->dist) {
+ searchPtr->elemPtr = (Element *)elemPtr;
+ searchPtr->dist = dMin;
+ searchPtr->index = iClose;
+ searchPtr->point.x = elemPtr->x.values[iClose];
+ searchPtr->point.y = elemPtr->y.values[iClose];
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetLineExtentsProc --
+ *
+ * Retrieves the range of the line element
+ *
+ * Results:
+ * Returns the number of data points in the element.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GetLineExtentsProc(Element *basePtr, Region2d *extsPtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ int np;
+
+ extsPtr->top = extsPtr->left = DBL_MAX;
+ extsPtr->bottom = extsPtr->right = -DBL_MAX;
+
+ np = NUMBEROFPOINTS(elemPtr);
+ if (np < 1) {
+ return;
+ }
+ extsPtr->right = elemPtr->x.max;
+ if ((elemPtr->x.min <= 0.0) && (elemPtr->axes.x->logScale)) {
+ extsPtr->left = Blt_FindElemValuesMinimum(&elemPtr->x, DBL_MIN);
+ } else {
+ extsPtr->left = elemPtr->x.min;
+ }
+ extsPtr->bottom = elemPtr->y.max;
+ if ((elemPtr->y.min <= 0.0) && (elemPtr->axes.y->logScale)) {
+ extsPtr->top = Blt_FindElemValuesMinimum(&elemPtr->y, DBL_MIN);
+ } else {
+ extsPtr->top = elemPtr->y.min;
+ }
+
+ /* Correct the data limits for error bars */
+
+ if (elemPtr->xError.nValues > 0) {
+ int i;
+
+ np = MIN(elemPtr->xError.nValues, np);
+ for (i = 0; i < np; i++) {
+ double x;
+
+ x = elemPtr->x.values[i] + elemPtr->xError.values[i];
+ if (x > extsPtr->right) {
+ extsPtr->right = x;
+ }
+ x = elemPtr->x.values[i] - elemPtr->xError.values[i];
+ if (elemPtr->axes.x->logScale) {
+ if (x < 0.0) {
+ x = -x; /* Mirror negative values, instead of
+ * ignoring them. */
+ }
+ if ((x > DBL_MIN) && (x < extsPtr->left)) {
+ extsPtr->left = x;
+ }
+ } else if (x < extsPtr->left) {
+ extsPtr->left = x;
+ }
+ }
+ } else {
+ if ((elemPtr->xHigh.nValues > 0) &&
+ (elemPtr->xHigh.max > extsPtr->right)) {
+ extsPtr->right = elemPtr->xHigh.max;
+ }
+ if (elemPtr->xLow.nValues > 0) {
+ double left;
+
+ if ((elemPtr->xLow.min <= 0.0) &&
+ (elemPtr->axes.x->logScale)) {
+ left = Blt_FindElemValuesMinimum(&elemPtr->xLow, DBL_MIN);
+ } else {
+ left = elemPtr->xLow.min;
+ }
+ if (left < extsPtr->left) {
+ extsPtr->left = left;
+ }
+ }
+ }
+
+ if (elemPtr->yError.nValues > 0) {
+ int i;
+
+ np = MIN(elemPtr->yError.nValues, np);
+ for (i = 0; i < np; i++) {
+ double y;
+
+ y = elemPtr->y.values[i] + elemPtr->yError.values[i];
+ if (y > extsPtr->bottom) {
+ extsPtr->bottom = y;
+ }
+ y = elemPtr->y.values[i] - elemPtr->yError.values[i];
+ if (elemPtr->axes.y->logScale) {
+ if (y < 0.0) {
+ y = -y; /* Mirror negative values, instead of
+ * ignoring them. */
+ }
+ if ((y > DBL_MIN) && (y < extsPtr->left)) {
+ extsPtr->top = y;
+ }
+ } else if (y < extsPtr->top) {
+ extsPtr->top = y;
+ }
+ }
+ } else {
+ if ((elemPtr->yHigh.nValues > 0) &&
+ (elemPtr->yHigh.max > extsPtr->bottom)) {
+ extsPtr->bottom = elemPtr->yHigh.max;
+ }
+ if (elemPtr->yLow.nValues > 0) {
+ double top;
+
+ if ((elemPtr->yLow.min <= 0.0) &&
+ (elemPtr->axes.y->logScale)) {
+ top = Blt_FindElemValuesMinimum(&elemPtr->yLow, DBL_MIN);
+ } else {
+ top = elemPtr->yLow.min;
+ }
+ if (top < extsPtr->top) {
+ extsPtr->top = top;
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BackgroundChangedProc
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+BackgroundChangedProc(ClientData clientData)
+{
+ Element *elemPtr = clientData;
+ Graph *graphPtr;
+
+ graphPtr = elemPtr->obj.graphPtr;
+ if (graphPtr->tkwin != NULL) {
+ graphPtr->flags |= REDRAW_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureLineProc --
+ *
+ * Sets up the appropriate configuration parameters in the GC. It is
+ * assumed the parameters have been previously set by a call to
+ * Blt_ConfigureWidget.
+ *
+ * Results:
+ * The return value is a standard TCL result. If TCL_ERROR is returned,
+ * then interp->result contains an error message.
+ *
+ * Side effects:
+ * Configuration information such as line width, line style, color
+ * etc. get set in a new GC.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ConfigureLineProc(Graph *graphPtr, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ unsigned long gcMask;
+ XGCValues gcValues;
+ GC newGC;
+ Blt_ChainLink link;
+ LineStyle *stylePtr;
+
+ if (ConfigurePenProc(graphPtr, (Pen *)&elemPtr->builtinPen) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Point to the static normal/active pens if no external pens have been
+ * selected.
+ */
+ link = Blt_Chain_FirstLink(elemPtr->styles);
+ if (link == NULL) {
+ link = Blt_Chain_AllocLink(sizeof(LineStyle));
+ Blt_Chain_LinkAfter(elemPtr->styles, link, NULL);
+ }
+ stylePtr = Blt_Chain_GetValue(link);
+ stylePtr->penPtr = NORMALPEN(elemPtr);
+
+ if (elemPtr->fillBg != NULL) {
+ Blt_SetBackgroundChangedProc(elemPtr->fillBg, BackgroundChangedProc,
+ elemPtr);
+ }
+ /*
+ * Set the outline GC for this pen: GCForeground is outline color.
+ * GCBackground is the fill color (only used for bitmap symbols).
+ */
+ gcMask = 0;
+ if (elemPtr->fillFgColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = elemPtr->fillFgColor->pixel;
+ }
+ if (elemPtr->fillBgColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = elemPtr->fillBgColor->pixel;
+ }
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (elemPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, elemPtr->fillGC);
+ }
+ elemPtr->fillGC = newGC;
+
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-scalesymbols",
+ (char *)NULL)) {
+ elemPtr->flags |= (MAP_ITEM | SCALE_SYMBOL);
+ }
+ if (Blt_ConfigModified(elemPtr->configSpecs, "-pixels", "-trace",
+ "-*data", "-smooth", "-map*", "-label", "-hide", "-x", "-y",
+ "-areabackground", (char *)NULL)) {
+ elemPtr->flags |= MAP_ITEM;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClosestLineProc --
+ *
+ * Find the closest point or line segment (if interpolated) to the given
+ * window coordinate in the line element.
+ *
+ * Results:
+ * Returns the distance of the closest point among other information.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ClosestLineProc(Graph *graphPtr, Element *basePtr, ClosestSearch *searchPtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ int mode;
+
+ mode = searchPtr->mode;
+ if (mode == SEARCH_AUTO) {
+ LinePen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ mode = SEARCH_POINTS;
+ if ((NUMBEROFPOINTS(elemPtr) > 1) && (penPtr->traceWidth > 0)) {
+ mode = SEARCH_TRACES;
+ }
+ }
+ if (mode == SEARCH_POINTS) {
+ ClosestPoint(elemPtr, searchPtr);
+ } else {
+ DistanceProc *distProc;
+ int found;
+
+ if (searchPtr->along == SEARCH_X) {
+ distProc = DistanceToXProc;
+ } else if (searchPtr->along == SEARCH_Y) {
+ distProc = DistanceToYProc;
+ } else {
+ distProc = DistanceToLineProc;
+ }
+ found = ClosestTrace(graphPtr, elemPtr, searchPtr, distProc);
+ if ((!found) && (searchPtr->along != SEARCH_BOTH)) {
+ ClosestPoint(elemPtr, searchPtr);
+ }
+ }
+}
+
+/*
+ * XDrawLines() points: XMaxRequestSize(dpy) - 3
+ * XFillPolygon() points: XMaxRequestSize(dpy) - 4
+ * XDrawSegments() segments: (XMaxRequestSize(dpy) - 3) / 2
+ * XDrawRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
+ * XFillRectangles() rectangles: (XMaxRequestSize(dpy) - 3) / 2
+ * XDrawArcs() or XFillArcs() arcs: (XMaxRequestSize(dpy) - 3) / 3
+ */
+
+#define MAX_DRAWLINES(d) Blt_MaxRequestSize(d, sizeof(XPoint))
+#define MAX_DRAWPOLYGON(d) Blt_MaxRequestSize(d, sizeof(XPoint))
+#define MAX_DRAWSEGMENTS(d) Blt_MaxRequestSize(d, sizeof(XSegment))
+#define MAX_DRAWRECTANGLES(d) Blt_MaxRequestSize(d, sizeof(XRectangle))
+#define MAX_DRAWARCS(d) Blt_MaxRequestSize(d, sizeof(XArc))
+
+static void
+DrawCircles(Display *display, Drawable drawable, LineElement *elemPtr,
+ LinePen *penPtr, int nSymbolPts, Point2d *symbolPts, int radius)
+{
+ int i;
+ XArc *arcs; /* Array of arcs (circle) */
+ int reqSize;
+ int s;
+ int count;
+
+ s = radius + radius;
+ arcs = malloc(nSymbolPts * sizeof(XArc));
+
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *pend;
+ XArc *ap;
+
+ ap = arcs;
+ count = 0;
+ for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ ap->x = Round(pp->x) - radius;
+ ap->y = Round(pp->y) - radius;
+ ap->width = ap->height = (unsigned short)s;
+ ap->angle1 = 0;
+ ap->angle2 = 23040;
+ ap++, count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *pend;
+ XArc *ap;
+
+ ap = arcs;
+ for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) {
+ ap->x = Round(pp->x) - radius;
+ ap->y = Round(pp->y) - radius;
+ ap->width = ap->height = (unsigned short)s;
+ ap->angle1 = 0;
+ ap->angle2 = 23040;
+ ap++;
+ }
+ count = nSymbolPts;
+ }
+ reqSize = MAX_DRAWARCS(display);
+ for (i = 0; i < count; i += reqSize) {
+ int n;
+
+ n = ((i + reqSize) > count) ? (count - i) : reqSize;
+ if (penPtr->symbol.fillGC != NULL) {
+ XFillArcs(display, drawable, penPtr->symbol.fillGC, arcs + i, n);
+ }
+ if (penPtr->symbol.outlineWidth > 0) {
+ XDrawArcs(display, drawable, penPtr->symbol.outlineGC, arcs + i, n);
+ }
+ }
+ free(arcs);
+}
+
+static void
+DrawSquares(Display *display, Drawable drawable, LineElement *elemPtr,
+ LinePen *penPtr, int nSymbolPts, Point2d *symbolPts, int r)
+{
+ XRectangle *rectangles;
+ XRectangle *rp, *rend;
+ int reqSize;
+ int s, count;
+
+ s = r + r;
+ rectangles = malloc(nSymbolPts * sizeof(XRectangle));
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *pend;
+ XRectangle *rp;
+
+ count = 0;
+ rp = rectangles;
+ for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ rp->x = Round(pp->x) - r;
+ rp->y = Round(pp->y) - r;
+ rp->width = rp->height = (unsigned short)s;
+ rp++, count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *pend;
+ XRectangle *rp;
+
+ rp = rectangles;
+ for (pp = symbolPts, pend = pp + nSymbolPts; pp < pend; pp++) {
+ rp->x = Round(pp->x) - r;
+ rp->y = Round(pp->y) - r;
+ rp->width = rp->height = (unsigned short)s;
+ rp++;
+ }
+ count = nSymbolPts;
+ }
+ reqSize = MAX_DRAWRECTANGLES(display) - 3;
+ for (rp = rectangles, rend = rp + count; rp < rend; rp += reqSize) {
+ int n;
+
+ n = rend - rp;
+ if (n > reqSize) {
+ n = reqSize;
+ }
+ if (penPtr->symbol.fillGC != NULL) {
+ XFillRectangles(display, drawable, penPtr->symbol.fillGC, rp, n);
+ }
+ if (penPtr->symbol.outlineWidth > 0) {
+ XDrawRectangles(display, drawable, penPtr->symbol.outlineGC, rp, n);
+ }
+ }
+ free(rectangles);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawSymbols --
+ *
+ * Draw the symbols centered at the each given x,y coordinate in the array
+ * of points.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Draws a symbol at each coordinate given. If active, only those
+ * coordinates which are currently active are drawn.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawSymbols(
+ Graph *graphPtr, /* Graph widget record */
+ Drawable drawable, /* Pixmap or window to draw into */
+ LineElement *elemPtr,
+ LinePen *penPtr,
+ int size, /* Size of element */
+ int nSymbolPts, /* Number of coordinates in array */
+ Point2d *symbolPts) /* Array of x,y coordinates for line */
+{
+ XPoint pattern[13]; /* Template for polygon symbols */
+ int r1, r2;
+ int count;
+#define SQRT_PI 1.77245385090552
+#define S_RATIO 0.886226925452758
+
+ if (size < 3) {
+ if (penPtr->symbol.fillGC != NULL) {
+ Point2d *pp, *endp;
+ XPoint *points, *xpp;
+
+ xpp = points = malloc(nSymbolPts * sizeof(XPoint));
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ xpp->x = Round(pp->x);
+ xpp->y = Round(pp->y);
+ xpp++;
+ }
+ XDrawPoints(graphPtr->display, drawable, penPtr->symbol.fillGC,
+ points, nSymbolPts, CoordModeOrigin);
+ free(points);
+ }
+ return;
+ }
+ r1 = (int)ceil(size * 0.5);
+ r2 = (int)ceil(size * S_RATIO * 0.5);
+
+ switch (penPtr->symbol.type) {
+ case SYMBOL_NONE:
+ break;
+
+ case SYMBOL_SQUARE:
+ DrawSquares(graphPtr->display, drawable, elemPtr, penPtr, nSymbolPts,
+ symbolPts, r2);
+ break;
+
+ case SYMBOL_CIRCLE:
+ DrawCircles(graphPtr->display, drawable, elemPtr, penPtr, nSymbolPts,
+ symbolPts, r1);
+ break;
+
+ case SYMBOL_SPLUS:
+ case SYMBOL_SCROSS:
+ {
+ XSegment *segments; /* Array of line segments (splus,
+ * scross) */
+ int i;
+ int reqSize, nSegs;
+
+ if (penPtr->symbol.type == SYMBOL_SCROSS) {
+ r2 = Round((double)r2 * M_SQRT1_2);
+ pattern[3].y = pattern[2].x = pattern[0].x = pattern[0].y = -r2;
+ pattern[3].x = pattern[2].y = pattern[1].y = pattern[1].x = r2;
+ } else {
+ pattern[0].y = pattern[1].y = pattern[2].x = pattern[3].x = 0;
+ pattern[0].x = pattern[2].y = -r2;
+ pattern[1].x = pattern[3].y = r2;
+ }
+ segments = malloc(nSymbolPts * 2 * sizeof(XSegment));
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+ XSegment *sp;
+
+ sp = segments;
+ count = 0;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ int rndx, rndy;
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ sp->x1 = pattern[0].x + rndx;
+ sp->y1 = pattern[0].y + rndy;
+ sp->x2 = pattern[1].x + rndx;
+ sp->y2 = pattern[1].y + rndy;
+ sp++;
+ sp->x1 = pattern[2].x + rndx;
+ sp->y1 = pattern[2].y + rndy;
+ sp->x2 = pattern[3].x + rndx;
+ sp->y2 = pattern[3].y + rndy;
+ sp++;
+ count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+ XSegment *sp;
+
+ sp = segments;
+ count = nSymbolPts;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int rndx, rndy;
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ sp->x1 = pattern[0].x + rndx;
+ sp->y1 = pattern[0].y + rndy;
+ sp->x2 = pattern[1].x + rndx;
+ sp->y2 = pattern[1].y + rndy;
+ sp++;
+ sp->x1 = pattern[2].x + rndx;
+ sp->y1 = pattern[2].y + rndy;
+ sp->x2 = pattern[3].x + rndx;
+ sp->y2 = pattern[3].y + rndy;
+ sp++;
+ }
+ }
+ nSegs = count * 2;
+ /* Always draw skinny symbols regardless of the outline width */
+ reqSize = MAX_DRAWSEGMENTS(graphPtr->display);
+ for (i = 0; i < nSegs; i += reqSize) {
+ int chunk;
+
+ chunk = ((i + reqSize) > nSegs) ? (nSegs - i) : reqSize;
+ XDrawSegments(graphPtr->display, drawable,
+ penPtr->symbol.outlineGC, segments + i, chunk);
+ }
+ free(segments);
+ }
+ break;
+
+ case SYMBOL_PLUS:
+ case SYMBOL_CROSS:
+ {
+ XPoint *polygon;
+ int d; /* Small delta for cross/plus
+ * thickness */
+
+ d = (r2 / 3);
+
+ /*
+ *
+ * 2 3 The plus/cross symbol is a closed polygon
+ * of 12 points. The diagram to the left
+ * 0,12 1 4 5 represents the positions of the points
+ * x,y which are computed below. The extra
+ * 11 10 7 6 (thirteenth) point connects the first and
+ * last points.
+ * 9 8
+ */
+
+ pattern[0].x = pattern[11].x = pattern[12].x = -r2;
+ pattern[2].x = pattern[1].x = pattern[10].x = pattern[9].x = -d;
+ pattern[3].x = pattern[4].x = pattern[7].x = pattern[8].x = d;
+ pattern[5].x = pattern[6].x = r2;
+ pattern[2].y = pattern[3].y = -r2;
+ pattern[0].y = pattern[1].y = pattern[4].y = pattern[5].y =
+ pattern[12].y = -d;
+ pattern[11].y = pattern[10].y = pattern[7].y = pattern[6].y = d;
+ pattern[9].y = pattern[8].y = r2;
+
+ if (penPtr->symbol.type == SYMBOL_CROSS) {
+ int i;
+
+ /* For the cross symbol, rotate the points by 45 degrees. */
+ for (i = 0; i < 12; i++) {
+ double dx, dy;
+
+ dx = (double)pattern[i].x * M_SQRT1_2;
+ dy = (double)pattern[i].y * M_SQRT1_2;
+ pattern[i].x = Round(dx - dy);
+ pattern[i].y = Round(dx + dy);
+ }
+ pattern[12] = pattern[0];
+ }
+ polygon = malloc(nSymbolPts * 13 * sizeof(XPoint));
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ count = 0;
+ xpp = polygon;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ int i;
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 13; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ xpp = polygon;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int i;
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 13; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ }
+ count = nSymbolPts;
+ }
+ if (penPtr->symbol.fillGC != NULL) {
+ int i;
+ XPoint *xpp;
+
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 13) {
+ XFillPolygon(graphPtr->display, drawable,
+ penPtr->symbol.fillGC, xpp, 13, Complex,
+ CoordModeOrigin);
+ }
+ }
+ if (penPtr->symbol.outlineWidth > 0) {
+ int i;
+ XPoint *xpp;
+
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 13) {
+ XDrawLines(graphPtr->display, drawable,
+ penPtr->symbol.outlineGC, xpp, 13, CoordModeOrigin);
+ }
+ }
+ free(polygon);
+ }
+ break;
+
+ case SYMBOL_DIAMOND:
+ {
+ XPoint *polygon;
+
+ /*
+ *
+ * The plus symbol is a closed polygon
+ * 1 of 4 points. The diagram to the left
+ * represents the positions of the points
+ * 0,4 x,y 2 which are computed below. The extra
+ * (fifth) point connects the first and
+ * 3 last points.
+ *
+ */
+ pattern[1].y = pattern[0].x = -r1;
+ pattern[2].y = pattern[3].x = pattern[0].y = pattern[1].x = 0;
+ pattern[3].y = pattern[2].x = r1;
+ pattern[4] = pattern[0];
+
+ polygon = malloc(nSymbolPts * 5 * sizeof(XPoint));
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ xpp = polygon;
+ count = 0;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int i;
+
+ if (DRAW_SYMBOL(elemPtr)) {
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 5; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ xpp = polygon;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int i;
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 5; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ }
+ count = nSymbolPts;
+ }
+ if (penPtr->symbol.fillGC != NULL) {
+ XPoint *xpp;
+ int i;
+
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 5) {
+ XFillPolygon(graphPtr->display, drawable,
+ penPtr->symbol.fillGC, xpp, 5, Convex, CoordModeOrigin);
+
+ }
+ }
+ if (penPtr->symbol.outlineWidth > 0) {
+ XPoint *xpp;
+ int i;
+
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 5) {
+ XDrawLines(graphPtr->display, drawable,
+ penPtr->symbol.outlineGC, xpp, 5, CoordModeOrigin);
+ }
+ }
+ free(polygon);
+ }
+ break;
+
+ case SYMBOL_TRIANGLE:
+ case SYMBOL_ARROW:
+ {
+ XPoint *polygon;
+ double b;
+ int b2, h1, h2;
+#define H_RATIO 1.1663402261671607
+#define B_RATIO 1.3467736870885982
+#define TAN30 0.57735026918962573
+#define COS30 0.86602540378443871
+
+ b = Round(size * B_RATIO * 0.7);
+ b2 = Round(b * 0.5);
+ h2 = Round(TAN30 * b2);
+ h1 = Round(b2 / COS30);
+ /*
+ *
+ * The triangle symbol is a closed polygon
+ * 0,3 of 3 points. The diagram to the left
+ * represents the positions of the points
+ * x,y which are computed below. The extra
+ * (fourth) point connects the first and
+ * 2 1 last points.
+ *
+ */
+
+ if (penPtr->symbol.type == SYMBOL_ARROW) {
+ pattern[3].x = pattern[0].x = 0;
+ pattern[3].y = pattern[0].y = h1;
+ pattern[1].x = b2;
+ pattern[2].y = pattern[1].y = -h2;
+ pattern[2].x = -b2;
+ } else {
+ pattern[3].x = pattern[0].x = 0;
+ pattern[3].y = pattern[0].y = -h1;
+ pattern[1].x = b2;
+ pattern[2].y = pattern[1].y = h2;
+ pattern[2].x = -b2;
+ }
+ polygon = malloc(nSymbolPts * 4 * sizeof(XPoint));
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ xpp = polygon;
+ count = 0;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int i;
+
+ if (DRAW_SYMBOL(elemPtr)) {
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 4; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ count++;
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+ XPoint *xpp;
+
+ xpp = polygon;
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int i;
+ int rndx, rndy;
+
+ rndx = Round(pp->x), rndy = Round(pp->y);
+ for (i = 0; i < 4; i++) {
+ xpp->x = pattern[i].x + rndx;
+ xpp->y = pattern[i].y + rndy;
+ xpp++;
+ }
+ }
+ count = nSymbolPts;
+ }
+ if (penPtr->symbol.fillGC != NULL) {
+ XPoint *xpp;
+ int i;
+
+ xpp = polygon;
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 4) {
+ XFillPolygon(graphPtr->display, drawable,
+ penPtr->symbol.fillGC, xpp, 4, Convex, CoordModeOrigin);
+ }
+ }
+ if (penPtr->symbol.outlineWidth > 0) {
+ XPoint *xpp;
+ int i;
+
+ xpp = polygon;
+ for (xpp = polygon, i = 0; i < count; i++, xpp += 4) {
+ XDrawLines(graphPtr->display, drawable,
+ penPtr->symbol.outlineGC, xpp, 4, CoordModeOrigin);
+ }
+ }
+ free(polygon);
+ }
+ break;
+
+ case SYMBOL_IMAGE:
+ {
+ int w, h;
+ int dx, dy;
+
+ Tk_SizeOfImage(penPtr->symbol.image, &w, &h);
+
+ dx = w / 2;
+ dy = h / 2;
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ int x, y;
+
+ x = Round(pp->x) - dx;
+ y = Round(pp->y) - dy;
+ Tk_RedrawImage(penPtr->symbol.image, 0, 0, w, h,
+ drawable, x, y);
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int x, y;
+
+ x = Round(pp->x) - dx;
+ y = Round(pp->y) - dy;
+ Tk_RedrawImage(penPtr->symbol.image, 0, 0, w, h,
+ drawable, x, y);
+ }
+ }
+ }
+ break;
+
+ case SYMBOL_BITMAP:
+ {
+ Pixmap bitmap, mask;
+ int w, h, bw, bh;
+ double scale, sx, sy;
+ int dx, dy;
+
+ Tk_SizeOfBitmap(graphPtr->display, penPtr->symbol.bitmap, &w, &h);
+ mask = None;
+
+ /*
+ * Compute the size of the scaled bitmap. Stretch the bitmap to fit
+ * a nxn bounding box.
+ */
+ sx = (double)size / (double)w;
+ sy = (double)size / (double)h;
+ scale = MIN(sx, sy);
+ bw = (int)(w * scale);
+ bh = (int)(h * scale);
+
+ XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC, None);
+ if (penPtr->symbol.mask != None) {
+ mask = Blt_ScaleBitmap(graphPtr->tkwin, penPtr->symbol.mask,
+ w, h, bw, bh);
+ XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC, mask);
+ }
+ bitmap = Blt_ScaleBitmap(graphPtr->tkwin, penPtr->symbol.bitmap,
+ w, h, bw, bh);
+ if (penPtr->symbol.fillGC == NULL) {
+ XSetClipMask(graphPtr->display, penPtr->symbol.outlineGC,
+ bitmap);
+ }
+ dx = bw / 2;
+ dy = bh / 2;
+ if (elemPtr->symbolInterval > 0) {
+ Point2d *pp, *endp;
+
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ if (DRAW_SYMBOL(elemPtr)) {
+ int x, y;
+
+ x = Round(pp->x) - dx;
+ y = Round(pp->y) - dy;
+ if ((penPtr->symbol.fillGC == NULL) || (mask !=None)) {
+ XSetClipOrigin(graphPtr->display,
+ penPtr->symbol.outlineGC, x, y);
+ }
+ XCopyPlane(graphPtr->display, bitmap, drawable,
+ penPtr->symbol.outlineGC, 0, 0, bw, bh, x, y, 1);
+ }
+ elemPtr->symbolCounter++;
+ }
+ } else {
+ Point2d *pp, *endp;
+
+ for (pp = symbolPts, endp = pp + nSymbolPts; pp < endp; pp++) {
+ int x, y;
+
+ x = Round(pp->x) - dx;
+ y = Round(pp->y) - dy;
+ if ((penPtr->symbol.fillGC == NULL) || (mask != None)) {
+ XSetClipOrigin(graphPtr->display,
+ penPtr->symbol.outlineGC, x, y);
+ }
+ XCopyPlane(graphPtr->display, bitmap, drawable,
+ penPtr->symbol.outlineGC, 0, 0, bw, bh, x, y, 1);
+ }
+ }
+ Tk_FreePixmap(graphPtr->display, bitmap);
+ if (mask != None) {
+ Tk_FreePixmap(graphPtr->display, mask);
+ }
+ }
+ break;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawSymbolProc --
+ *
+ * Draw the symbol centered at the each given x,y coordinate.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Draws a symbol at the coordinate given.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawSymbolProc(
+ Graph *graphPtr, /* Graph widget record */
+ Drawable drawable, /* Pixmap or window to draw into */
+ Element *basePtr, /* Line element information */
+ int x, int y, /* Center position of symbol */
+ int size) /* Size of symbol. */
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ LinePen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ if (penPtr->traceWidth > 0) {
+ /*
+ * Draw an extra line offset by one pixel from the previous to give a
+ * thicker appearance. This is only for the legend entry. This routine
+ * is never called for drawing the actual line segments.
+ */
+ XDrawLine(graphPtr->display, drawable, penPtr->traceGC, x - size, y,
+ x + size, y);
+ XDrawLine(graphPtr->display, drawable, penPtr->traceGC, x - size, y + 1,
+ x + size, y + 1);
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ Point2d point;
+
+ point.x = x, point.y = y;
+ DrawSymbols(graphPtr, drawable, elemPtr, penPtr, size, 1, &point);
+ }
+}
+
+static void
+DrawTraces(Graph *graphPtr, Drawable drawable, LineElement *elemPtr,
+ LinePen *penPtr)
+{
+ Blt_ChainLink link;
+ XPoint *points;
+ int np;
+
+ np = Blt_MaxRequestSize(graphPtr->display, sizeof(XPoint)) - 1;
+ points = malloc((np + 1) * sizeof(XPoint));
+
+ for (link = Blt_Chain_FirstLink(elemPtr->traces); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ XPoint *xpp;
+ bltTrace *tracePtr;
+ int remaining, count;
+ int n;
+
+ tracePtr = Blt_Chain_GetValue(link);
+
+ /*
+ * If the trace has to be split into separate XDrawLines calls, then the
+ * end point of the current trace is also the starting point of the new
+ * split.
+ */
+ /* Step 1. Convert and draw the first section of the trace.
+ * It may contain the entire trace. */
+
+ n = MIN(np, tracePtr->screenPts.length);
+ for (xpp = points, count = 0; count < n; count++, xpp++) {
+ xpp->x = Round(tracePtr->screenPts.points[count].x);
+ xpp->y = Round(tracePtr->screenPts.points[count].y);
+ }
+ XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
+ count, CoordModeOrigin);
+
+ /* Step 2. Next handle any full-size chunks left. */
+
+ while ((count + np) < tracePtr->screenPts.length) {
+ int j;
+
+ /* Start with the last point of the previous trace. */
+ points[0].x = points[np - 1].x;
+ points[0].y = points[np - 1].y;
+
+ for (xpp = points + 1, j = 0; j < np; j++, count++, xpp++) {
+ xpp->x = Round(tracePtr->screenPts.points[count].x);
+ xpp->y = Round(tracePtr->screenPts.points[count].y);
+ }
+ XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
+ np + 1, CoordModeOrigin);
+ }
+
+ /* Step 3. Convert and draw the remaining points. */
+
+ remaining = tracePtr->screenPts.length - count;
+ if (remaining > 0) {
+ /* Start with the last point of the previous trace. */
+ points[0].x = points[np - 1].x;
+ points[0].y = points[np - 1].y;
+ for (xpp = points + 1; count < tracePtr->screenPts.length; count++,
+ xpp++) {
+ xpp->x = Round(tracePtr->screenPts.points[count].x);
+ xpp->y = Round(tracePtr->screenPts.points[count].y);
+ }
+ XDrawLines(graphPtr->display, drawable, penPtr->traceGC, points,
+ remaining + 1, CoordModeOrigin);
+ }
+ }
+ free(points);
+}
+
+static void
+DrawValues(Graph *graphPtr, Drawable drawable, LineElement *elemPtr,
+ LinePen *penPtr, int length, Point2d *points, int *map)
+{
+ Point2d *pp, *endp;
+ double *xval, *yval;
+ const char *fmt;
+ char string[TCL_DOUBLE_SPACE * 2 + 2];
+ int count;
+
+ fmt = penPtr->valueFormat;
+ if (fmt == NULL) {
+ fmt = "%g";
+ }
+ count = 0;
+ xval = elemPtr->x.values, yval = elemPtr->y.values;
+ for (pp = points, endp = points + length; pp < endp; pp++) {
+ double x, y;
+
+ x = xval[map[count]];
+ y = yval[map[count]];
+ count++;
+ if (penPtr->valueShow == SHOW_X) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ } else if (penPtr->valueShow == SHOW_Y) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, y);
+ } else if (penPtr->valueShow == SHOW_BOTH) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ strcat(string, ",");
+ sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y);
+ }
+ Blt_DrawText(graphPtr->tkwin, drawable, string, &penPtr->valueStyle,
+ Round(pp->x), Round(pp->y));
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawActiveLineProc --
+ *
+ * Draws the connected line(s) representing the element. If the line is
+ * made up of non-line symbols and the line width parameter has been set
+ * (linewidth > 0), the element will also be drawn as a line (with the
+ * linewidth requested). The line may consist of separate line segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * X drawing commands are output.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawActiveLineProc(Graph *graphPtr, Drawable drawable, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ LinePen *penPtr = (LinePen *)elemPtr->activePenPtr;
+ int symbolSize;
+
+ if (penPtr == NULL) {
+ return;
+ }
+ symbolSize = ScaleSymbol(elemPtr, penPtr->symbol.size);
+
+ /*
+ * nActiveIndices
+ * > 0 Some points are active. Uses activeArr.
+ * < 0 All points are active.
+ * == 0 No points are active.
+ */
+ if (elemPtr->nActiveIndices > 0) {
+ if (elemPtr->flags & ACTIVE_PENDING) {
+ MapActiveSymbols(graphPtr, elemPtr);
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ DrawSymbols(graphPtr, drawable, elemPtr, penPtr, symbolSize,
+ elemPtr->activePts.length, elemPtr->activePts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawValues(graphPtr, drawable, elemPtr, penPtr,
+ elemPtr->activePts.length,
+ elemPtr->activePts.points,
+ elemPtr->activePts.map);
+ }
+ } else if (elemPtr->nActiveIndices < 0) {
+ if (penPtr->traceWidth > 0) {
+ if (elemPtr->lines.length > 0) {
+ Blt_Draw2DSegments(graphPtr->display, drawable,
+ penPtr->traceGC, elemPtr->lines.segments,
+ elemPtr->lines.length);
+ } else if (Blt_Chain_GetLength(elemPtr->traces) > 0) {
+ DrawTraces(graphPtr, drawable, elemPtr, penPtr);
+ }
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ DrawSymbols(graphPtr, drawable, elemPtr, penPtr, symbolSize,
+ elemPtr->symbolPts.length, elemPtr->symbolPts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawValues(graphPtr, drawable, elemPtr, penPtr,
+ elemPtr->symbolPts.length, elemPtr->symbolPts.points,
+ elemPtr->symbolPts.map);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawNormalLine --
+ *
+ * Draws the connected line(s) representing the element. If the line is
+ * made up of non-line symbols and the line width parameter has been set
+ * (linewidth > 0), the element will also be drawn as a line (with the
+ * linewidth requested). The line may consist of separate line segments.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * X drawing commands are output.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawNormalLineProc(Graph *graphPtr, Drawable drawable, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ Blt_ChainLink link;
+ unsigned int count;
+
+ /* Fill area under the curve */
+ if (elemPtr->fillPts != NULL) {
+ XPoint *points;
+ Point2d *endp, *pp;
+
+ points = malloc(sizeof(XPoint) * elemPtr->nFillPts);
+ count = 0;
+ for (pp = elemPtr->fillPts, endp = pp + elemPtr->nFillPts;
+ pp < endp; pp++) {
+ points[count].x = Round(pp->x);
+ points[count].y = Round(pp->y);
+ count++;
+ }
+ if (elemPtr->fillBg != NULL) {
+ Blt_SetBackgroundOrigin(graphPtr->tkwin, elemPtr->fillBg, 0, 0);
+ Blt_FillBackgroundPolygon(graphPtr->tkwin, drawable,
+ elemPtr->fillBg, points, elemPtr->nFillPts, 0, TK_RELIEF_FLAT);
+ }
+ free(points);
+ }
+
+ /* Lines: stripchart segments or graph traces. */
+ if (elemPtr->lines.length > 0) {
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ LinePen *penPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = (LinePen *)stylePtr->penPtr;
+ if ((stylePtr->lines.length > 0) &&
+ (penPtr->errorBarLineWidth > 0)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->traceGC,
+ stylePtr->lines.segments, stylePtr->lines.length);
+ }
+ }
+ } else {
+ LinePen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ if ((Blt_Chain_GetLength(elemPtr->traces) > 0) &&
+ (penPtr->traceWidth > 0)) {
+ DrawTraces(graphPtr, drawable, elemPtr, penPtr);
+ }
+ }
+
+ if (elemPtr->reqMaxSymbols > 0) {
+ int total;
+
+ total = 0;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ total += stylePtr->symbolPts.length;
+ }
+ elemPtr->symbolInterval = total / elemPtr->reqMaxSymbols;
+ elemPtr->symbolCounter = 0;
+ }
+
+ /* Symbols, error bars, values. */
+
+ count = 0;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ LinePen *penPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = (LinePen *)stylePtr->penPtr;
+ if ((stylePtr->xeb.length > 0) && (penPtr->errorBarShow & SHOW_X)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
+ stylePtr->xeb.segments, stylePtr->xeb.length);
+ }
+ if ((stylePtr->yeb.length > 0) && (penPtr->errorBarShow & SHOW_Y)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, penPtr->errorBarGC,
+ stylePtr->yeb.segments, stylePtr->yeb.length);
+ }
+ if ((stylePtr->symbolPts.length > 0) &&
+ (penPtr->symbol.type != SYMBOL_NONE)) {
+ DrawSymbols(graphPtr, drawable, elemPtr, penPtr,
+ stylePtr->symbolSize, stylePtr->symbolPts.length,
+ stylePtr->symbolPts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ DrawValues(graphPtr, drawable, elemPtr, penPtr,
+ stylePtr->symbolPts.length, stylePtr->symbolPts.points,
+ elemPtr->symbolPts.map + count);
+ }
+ count += stylePtr->symbolPts.length;
+ }
+ elemPtr->symbolInterval = 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetSymbolPostScriptInfo --
+ *
+ * Set up the PostScript environment with the macros and attributes needed
+ * to draw the symbols of the element.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GetSymbolPostScriptInfo(
+ Graph *graphPtr,
+ Blt_Ps ps,
+ LinePen *penPtr,
+ int size)
+{
+ XColor *outlineColor, *fillColor, *defaultColor;
+
+ /* Set line and foreground attributes */
+ outlineColor = penPtr->symbol.outlineColor;
+ fillColor = penPtr->symbol.fillColor;
+ defaultColor = penPtr->traceColor;
+
+ if (fillColor == COLOR_DEFAULT) {
+ fillColor = defaultColor;
+ }
+ if (outlineColor == COLOR_DEFAULT) {
+ outlineColor = defaultColor;
+ }
+ if (penPtr->symbol.type == SYMBOL_NONE) {
+ Blt_Ps_XSetLineAttributes(ps, defaultColor, penPtr->traceWidth + 2,
+ &penPtr->traceDashes, CapButt, JoinMiter);
+ } else {
+ Blt_Ps_XSetLineWidth(ps, penPtr->symbol.outlineWidth);
+ Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
+ }
+
+ /*
+ * Build a PostScript procedure to draw the symbols. For bitmaps, paint
+ * both the bitmap and its mask. Otherwise fill and stroke the path formed
+ * already.
+ */
+ Blt_Ps_Append(ps, "\n/DrawSymbolProc {\n");
+ switch (penPtr->symbol.type) {
+ case SYMBOL_NONE:
+ break; /* Do nothing */
+ case SYMBOL_BITMAP:
+ {
+ int w, h;
+ double sx, sy, scale;
+
+ /*
+ * Compute how much to scale the bitmap. Don't let the scaled
+ * bitmap exceed the bounding square for the symbol.
+ */
+ Tk_SizeOfBitmap(graphPtr->display, penPtr->symbol.bitmap, &w, &h);
+ sx = (double)size / (double)w;
+ sy = (double)size / (double)h;
+ scale = MIN(sx, sy);
+
+ if ((penPtr->symbol.mask != None) && (fillColor != NULL)) {
+ Blt_Ps_VarAppend(ps, "\n % Bitmap mask is \"",
+ Tk_NameOfBitmap(graphPtr->display, penPtr->symbol.mask),
+ "\"\n\n ", (char *)NULL);
+ Blt_Ps_XSetBackground(ps, fillColor);
+ Blt_Ps_DrawBitmap(ps, graphPtr->display, penPtr->symbol.mask,
+ scale, scale);
+ }
+ Blt_Ps_VarAppend(ps, "\n % Bitmap symbol is \"",
+ Tk_NameOfBitmap(graphPtr->display, penPtr->symbol.bitmap),
+ "\"\n\n ", (char *)NULL);
+ Blt_Ps_XSetForeground(ps, outlineColor);
+ Blt_Ps_DrawBitmap(ps, graphPtr->display, penPtr->symbol.bitmap,
+ scale, scale);
+ }
+ break;
+ default:
+ if (fillColor != NULL) {
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetBackground(ps, fillColor);
+ Blt_Ps_Append(ps, " gsave fill grestore\n");
+ }
+ if ((outlineColor != NULL) && (penPtr->symbol.outlineWidth > 0)) {
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetForeground(ps, outlineColor);
+ Blt_Ps_Append(ps, " stroke\n");
+ }
+ break;
+ }
+ Blt_Ps_Append(ps, "} def\n\n");
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SymbolsToPostScript --
+ *
+ * Draw a symbol centered at the given x,y window coordinate based upon the
+ * element symbol type and size.
+ *
+ * Results:
+ * None.
+ *
+ * Problems:
+ * Most notable is the round-off errors generated when calculating the
+ * centered position of the symbol.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+SymbolsToPostScript(
+ Graph *graphPtr,
+ Blt_Ps ps,
+ LinePen *penPtr,
+ int size,
+ int nSymbolPts,
+ Point2d *symbolPts)
+{
+ double symbolSize;
+ static const char *symbolMacros[] =
+ {
+ "Li", "Sq", "Ci", "Di", "Pl", "Cr", "Sp", "Sc", "Tr", "Ar", "Bm",
+ (char *)NULL,
+ };
+ GetSymbolPostScriptInfo(graphPtr, ps, penPtr, size);
+
+ symbolSize = (double)size;
+ switch (penPtr->symbol.type) {
+ case SYMBOL_SQUARE:
+ case SYMBOL_CROSS:
+ case SYMBOL_PLUS:
+ case SYMBOL_SCROSS:
+ case SYMBOL_SPLUS:
+ symbolSize = (double)Round(size * S_RATIO);
+ break;
+ case SYMBOL_TRIANGLE:
+ case SYMBOL_ARROW:
+ symbolSize = (double)Round(size * 0.7);
+ break;
+ case SYMBOL_DIAMOND:
+ symbolSize = (double)Round(size * M_SQRT1_2);
+ break;
+
+ default:
+ break;
+ }
+ {
+ Point2d *pp, *endp;
+
+ for (pp = symbolPts, endp = symbolPts + nSymbolPts; pp < endp; pp++) {
+ Blt_Ps_Format(ps, "%g %g %g %s\n", pp->x, pp->y,
+ symbolSize, symbolMacros[penPtr->symbol.type]);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SymbolToPostScriptProc --
+ *
+ * Draw the symbol centered at the each given x,y coordinate.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Draws a symbol at the coordinate given.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+SymbolToPostScriptProc(
+ Graph *graphPtr, /* Graph widget record */
+ Blt_Ps ps,
+ Element *basePtr, /* Line element information */
+ double x, double y, /* Center position of symbol */
+ int size) /* Size of element */
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ LinePen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ if (penPtr->traceWidth > 0) {
+ /*
+ * Draw an extra line offset by one pixel from the previous to give a
+ * thicker appearance. This is only for the legend entry. This routine
+ * is never called for drawing the actual line segments.
+ */
+ Blt_Ps_XSetLineAttributes(ps, penPtr->traceColor,
+ penPtr->traceWidth, &penPtr->traceDashes, CapButt, JoinMiter);
+ Blt_Ps_Format(ps, "%g %g %d Li\n", x, y, size + size);
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ Point2d point;
+
+ point.x = x, point.y = y;
+ SymbolsToPostScript(graphPtr, ps, penPtr, size, 1, &point);
+ }
+}
+
+static void
+SetLineAttributes(Blt_Ps ps, LinePen *penPtr)
+{
+ /* Set the attributes of the line (color, dashes, linewidth) */
+ Blt_Ps_XSetLineAttributes(ps, penPtr->traceColor,
+ penPtr->traceWidth, &penPtr->traceDashes, CapButt, JoinMiter);
+ if ((LineIsDashed(penPtr->traceDashes)) &&
+ (penPtr->traceOffColor != NULL)) {
+ Blt_Ps_Append(ps, "/DashesProc {\n gsave\n ");
+ Blt_Ps_XSetBackground(ps, penPtr->traceOffColor);
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
+ Blt_Ps_Append(ps, "stroke\n grestore\n} def\n");
+ } else {
+ Blt_Ps_Append(ps, "/DashesProc {} def\n");
+ }
+}
+
+static void
+TracesToPostScript(Blt_Ps ps, LineElement *elemPtr, LinePen *penPtr)
+{
+ Blt_ChainLink link;
+
+ SetLineAttributes(ps, penPtr);
+ for (link = Blt_Chain_FirstLink(elemPtr->traces); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ bltTrace *tracePtr;
+
+ tracePtr = Blt_Chain_GetValue(link);
+ if (tracePtr->screenPts.length > 0) {
+ Blt_Ps_Append(ps, "% start trace\n");
+ Blt_Ps_DrawPolyline(ps, tracePtr->screenPts.points,
+ tracePtr->screenPts.length);
+ Blt_Ps_Append(ps, "% end trace\n");
+ }
+ }
+}
+
+
+static void
+ValuesToPostScript(Blt_Ps ps, LineElement *elemPtr, LinePen *penPtr,
+ int nSymbolPts, Point2d *symbolPts, int *pointToData)
+{
+ Point2d *pp, *endp;
+ int count;
+ char string[TCL_DOUBLE_SPACE * 2 + 2];
+ const char *fmt;
+
+ fmt = penPtr->valueFormat;
+ if (fmt == NULL) {
+ fmt = "%g";
+ }
+ count = 0;
+ for (pp = symbolPts, endp = symbolPts + nSymbolPts; pp < endp; pp++) {
+ double x, y;
+
+ x = elemPtr->x.values[pointToData[count]];
+ y = elemPtr->y.values[pointToData[count]];
+ count++;
+ if (penPtr->valueShow == SHOW_X) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ } else if (penPtr->valueShow == SHOW_Y) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, y);
+ } else if (penPtr->valueShow == SHOW_BOTH) {
+ sprintf_s(string, TCL_DOUBLE_SPACE, fmt, x);
+ strcat(string, ",");
+ sprintf_s(string + strlen(string), TCL_DOUBLE_SPACE, fmt, y);
+ }
+ Blt_Ps_DrawText(ps, string, &penPtr->valueStyle, pp->x, pp->y);
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ActiveLineToPostScript --
+ *
+ * Generates PostScript commands to draw as "active" the points (symbols)
+ * and or line segments (trace) representing the element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript pen width, dashes, and color settings are changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ActiveLineToPostScriptProc(Graph *graphPtr, Blt_Ps ps, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ LinePen *penPtr = (LinePen *)elemPtr->activePenPtr;
+ int symbolSize;
+
+ if (penPtr == NULL) {
+ return;
+ }
+ symbolSize = ScaleSymbol(elemPtr, penPtr->symbol.size);
+ if (elemPtr->nActiveIndices > 0) {
+ if (elemPtr->flags & ACTIVE_PENDING) {
+ MapActiveSymbols(graphPtr, elemPtr);
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ SymbolsToPostScript(graphPtr, ps, penPtr, symbolSize,
+ elemPtr->activePts.length, elemPtr->activePts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ ValuesToPostScript(ps, elemPtr, penPtr, elemPtr->activePts.length,
+ elemPtr->activePts.points, elemPtr->activePts.map);
+ }
+ } else if (elemPtr->nActiveIndices < 0) {
+ if (penPtr->traceWidth > 0) {
+ if (elemPtr->lines.length > 0) {
+ SetLineAttributes(ps, penPtr);
+ Blt_Ps_Draw2DSegments(ps, elemPtr->lines.segments,
+ elemPtr->lines.length);
+ }
+ if (Blt_Chain_GetLength(elemPtr->traces) > 0) {
+ TracesToPostScript(ps, elemPtr, (LinePen *)penPtr);
+ }
+ }
+ if (penPtr->symbol.type != SYMBOL_NONE) {
+ SymbolsToPostScript(graphPtr, ps, penPtr, symbolSize,
+ elemPtr->symbolPts.length, elemPtr->symbolPts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ ValuesToPostScript(ps, elemPtr, penPtr, elemPtr->symbolPts.length,
+ elemPtr->symbolPts.points, elemPtr->symbolPts.map);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NormalLineToPostScriptProc --
+ *
+ * Similar to the DrawLine procedure, prints PostScript related commands to
+ * form the connected line(s) representing the element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript pen width, dashes, and color settings are changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+NormalLineToPostScriptProc(Graph *graphPtr, Blt_Ps ps, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+ Blt_ChainLink link;
+ unsigned int count;
+
+ /* Draw fill area */
+ if (elemPtr->fillPts != NULL) {
+ /* Create a path to use for both the polygon and its outline. */
+ Blt_Ps_Append(ps, "% start fill area\n");
+ Blt_Ps_Polyline(ps, elemPtr->fillPts, elemPtr->nFillPts);
+
+ /* If the background fill color was specified, draw the polygon in a
+ * solid fashion with that color. */
+ if (elemPtr->fillBgColor != NULL) {
+ Blt_Ps_XSetBackground(ps, elemPtr->fillBgColor);
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ }
+ Blt_Ps_XSetForeground(ps, elemPtr->fillFgColor);
+ if (elemPtr->fillBg != NULL) {
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ /* TBA: Transparent tiling is the hard part. */
+ } else {
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ }
+ Blt_Ps_Append(ps, "% end fill area\n");
+ }
+
+ /* Draw lines (strip chart) or traces (xy graph) */
+ if (elemPtr->lines.length > 0) {
+ for (link = Blt_Chain_FirstLink(elemPtr->styles); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ LinePen *penPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = (LinePen *)stylePtr->penPtr;
+ if ((stylePtr->lines.length > 0) && (penPtr->traceWidth > 0)) {
+ SetLineAttributes(ps, penPtr);
+ Blt_Ps_Append(ps, "% start segments\n");
+ Blt_Ps_Draw2DSegments(ps, stylePtr->lines.segments,
+ stylePtr->lines.length);
+ Blt_Ps_Append(ps, "% end segments\n");
+ }
+ }
+ } else {
+ LinePen *penPtr;
+
+ penPtr = NORMALPEN(elemPtr);
+ if ((Blt_Chain_GetLength(elemPtr->traces) > 0) &&
+ (penPtr->traceWidth > 0)) {
+ TracesToPostScript(ps, elemPtr, penPtr);
+ }
+ }
+
+ /* Draw symbols, error bars, values. */
+
+ count = 0;
+ for (link = Blt_Chain_FirstLink(elemPtr->styles); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ LineStyle *stylePtr;
+ LinePen *penPtr;
+ XColor *colorPtr;
+
+ stylePtr = Blt_Chain_GetValue(link);
+ penPtr = (LinePen *)stylePtr->penPtr;
+ colorPtr = penPtr->errorBarColor;
+ if (colorPtr == COLOR_DEFAULT) {
+ colorPtr = penPtr->traceColor;
+ }
+ if ((stylePtr->xeb.length > 0) && (penPtr->errorBarShow & SHOW_X)) {
+ Blt_Ps_XSetLineAttributes(ps, colorPtr, penPtr->errorBarLineWidth,
+ NULL, CapButt, JoinMiter);
+ Blt_Ps_Draw2DSegments(ps, stylePtr->xeb.segments,
+ stylePtr->xeb.length);
+ }
+ if ((stylePtr->yeb.length > 0) && (penPtr->errorBarShow & SHOW_Y)) {
+ Blt_Ps_XSetLineAttributes(ps, colorPtr, penPtr->errorBarLineWidth,
+ NULL, CapButt, JoinMiter);
+ Blt_Ps_Draw2DSegments(ps, stylePtr->yeb.segments,
+ stylePtr->yeb.length);
+ }
+ if ((stylePtr->symbolPts.length > 0) &&
+ (penPtr->symbol.type != SYMBOL_NONE)) {
+ SymbolsToPostScript(graphPtr, ps, penPtr, stylePtr->symbolSize,
+ stylePtr->symbolPts.length, stylePtr->symbolPts.points);
+ }
+ if (penPtr->valueShow != SHOW_NONE) {
+ ValuesToPostScript(ps, elemPtr, penPtr, stylePtr->symbolPts.length,
+ stylePtr->symbolPts.points, elemPtr->symbolPts.map + count);
+ }
+ count += stylePtr->symbolPts.length;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyLineProc --
+ *
+ * Release memory and resources allocated for the line element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the line element is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+DestroyLineProc(Graph *graphPtr, Element *basePtr)
+{
+ LineElement *elemPtr = (LineElement *)basePtr;
+
+ DestroyPenProc(graphPtr, (Pen *)&elemPtr->builtinPen);
+ if (elemPtr->activePenPtr != NULL) {
+ Blt_FreePen((Pen *)elemPtr->activePenPtr);
+ }
+ ResetLine(elemPtr);
+ if (elemPtr->styles != NULL) {
+ Blt_FreeStylePalette(elemPtr->styles);
+ Blt_Chain_Destroy(elemPtr->styles);
+ }
+ if (elemPtr->activeIndices != NULL) {
+ free(elemPtr->activeIndices);
+ }
+ if (elemPtr->fillPts != NULL) {
+ free(elemPtr->fillPts);
+ }
+ if (elemPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, elemPtr->fillGC);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_LineElement --
+ *
+ * Allocate memory and initialize methods for the new line element.
+ *
+ * Results:
+ * The pointer to the newly allocated element structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the line element structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static ElementProcs lineProcs =
+{
+ ClosestLineProc, /* Finds the closest element/data
+ * point */
+ ConfigureLineProc, /* Configures the element. */
+ DestroyLineProc, /* Destroys the element. */
+ DrawActiveLineProc, /* Draws active element */
+ DrawNormalLineProc, /* Draws normal element */
+ DrawSymbolProc, /* Draws the element symbol. */
+ GetLineExtentsProc, /* Find the extents of the element's
+ * data. */
+ ActiveLineToPostScriptProc, /* Prints active element. */
+ NormalLineToPostScriptProc, /* Prints normal element. */
+ SymbolToPostScriptProc, /* Prints the line's symbol. */
+ MapLineProc /* Compute element's screen
+ * coordinates. */
+};
+
+Element *
+Blt_LineElement(Graph *graphPtr, const char *name, ClassId classId)
+{
+ LineElement *elemPtr;
+
+ elemPtr = calloc(1, sizeof(LineElement));
+ elemPtr->procsPtr = &lineProcs;
+ elemPtr->configSpecs = lineElemConfigSpecs;
+ elemPtr->obj.name = Blt_Strdup(name);
+ Blt_GraphSetObjectClass(&elemPtr->obj, classId);
+ elemPtr->flags = SCALE_SYMBOL;
+ elemPtr->obj.graphPtr = graphPtr;
+ /* By default an element's name and label are the same. */
+ elemPtr->label = Blt_Strdup(name);
+ elemPtr->legendRelief = TK_RELIEF_FLAT;
+ elemPtr->penDir = PEN_BOTH_DIRECTIONS;
+ elemPtr->styles = Blt_Chain_Create();
+ elemPtr->builtinPenPtr = &elemPtr->builtinPen;
+ elemPtr->reqSmooth = PEN_SMOOTH_LINEAR;
+ InitLinePen(elemPtr->builtinPenPtr);
+ bltLineStylesOption.clientData = (ClientData)sizeof(LineStyle);
+ return (Element *)elemPtr;
+}
+
diff --git a/tlt3.0/bltGrMarker.c b/tlt3.0/bltGrMarker.c
new file mode 100644
index 0000000..89f587b
--- /dev/null
+++ b/tlt3.0/bltGrMarker.c
@@ -0,0 +1,4372 @@
+/*
+ * bltGrMarker.c --
+ *
+ * This module implements markers for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltImage.h"
+#include "bltGrElem.h"
+#include "bltBitmap.h"
+
+typedef int (GraphMarkerProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+#define GETBITMAP(b) \
+ (((b)->destBitmap == None) ? (b)->srcBitmap : (b)->destBitmap)
+
+#define MAX_OUTLINE_POINTS 12
+
+#define IMAGE_PHOTO (1<<7)
+
+/* Map graph coordinates to normalized coordinates [0..1] */
+#define NORMALIZE(A,x) (((x) - (A)->axisRange.min) * (A)->axisRange.scale)
+
+#define DEF_MARKER_ANCHOR "center"
+#define DEF_MARKER_BACKGROUND RGB_WHITE
+#define DEF_MARKER_BITMAP (char *)NULL
+#define DEF_MARKER_CAP_STYLE "butt"
+#define DEF_MARKER_COORDS (char *)NULL
+#define DEF_MARKER_DASHES (char *)NULL
+#define DEF_MARKER_DASH_OFFSET "0"
+#define DEF_MARKER_ELEMENT (char *)NULL
+#define DEF_MARKER_FOREGROUND RGB_BLACK
+#define DEF_MARKER_FILL_COLOR RGB_RED
+#define DEF_MARKER_FONT STD_FONT
+#define DEF_MARKER_GAP_COLOR RGB_PINK
+#define DEF_MARKER_HEIGHT "0"
+#define DEF_MARKER_HIDE "no"
+#define DEF_MARKER_JOIN_STYLE "miter"
+#define DEF_MARKER_JUSTIFY "left"
+#define DEF_MARKER_LINE_WIDTH "1"
+#define DEF_MARKER_MAP_X "x"
+#define DEF_MARKER_MAP_Y "y"
+#define DEF_MARKER_NAME (char *)NULL
+#define DEF_MARKER_OUTLINE_COLOR RGB_BLACK
+#define DEF_MARKER_PAD "4"
+#define DEF_MARKER_ANGLE "0.0"
+#define DEF_MARKER_SCALE "1.0"
+#define DEF_MARKER_STATE "normal"
+#define DEF_MARKER_STIPPLE (char *)NULL
+#define DEF_MARKER_TEXT (char *)NULL
+#define DEF_MARKER_UNDER "no"
+#define DEF_MARKER_WIDTH "0"
+#define DEF_MARKER_WINDOW (char *)NULL
+#define DEF_MARKER_XOR "no"
+#define DEF_MARKER_X_OFFSET "0"
+#define DEF_MARKER_Y_OFFSET "0"
+#define DEF_MARKER_FILTER "box"
+
+#define DEF_TEXT_TAGS "Text all"
+#define DEF_IMAGE_TAGS "Image all"
+#define DEF_BITMAP_TAGS "Bitmap all"
+#define DEF_WINDOW_TAGS "Window all"
+#define DEF_POLYGON_TAGS "Polygon all"
+#define DEF_LINE_TAGS "Line all"
+
+static Blt_OptionParseProc ObjToCoordsProc;
+static Blt_OptionPrintProc CoordsToObjProc;
+static Blt_OptionFreeProc FreeCoordsProc;
+static Blt_CustomOption coordsOption =
+{
+ ObjToCoordsProc, CoordsToObjProc, FreeCoordsProc, (ClientData)0
+};
+static Blt_OptionFreeProc FreeColorPairProc;
+static Blt_OptionParseProc ObjToColorPairProc;
+static Blt_OptionPrintProc ColorPairToObjProc;
+static Blt_CustomOption colorPairOption =
+{
+ ObjToColorPairProc, ColorPairToObjProc, FreeColorPairProc, (ClientData)0
+};
+
+extern Blt_CustomOption bltXAxisOption;
+extern Blt_CustomOption bltYAxisOption;
+extern Blt_CustomOption bltFilterOption;
+
+typedef Marker *(MarkerCreateProc)(void);
+typedef void (MarkerDrawProc)(Marker *markerPtr, Drawable drawable);
+typedef void (MarkerFreeProc)(Marker *markerPtr);
+typedef int (MarkerConfigProc)(Marker *markerPtr);
+typedef void (MarkerMapProc)(Marker *markerPtr);
+typedef void (MarkerPostscriptProc)(Marker *markerPtr, Blt_Ps ps);
+typedef int (MarkerPointProc)(Marker *markerPtr, Point2d *samplePtr);
+typedef int (MarkerRegionProc)(Marker *markerPtr, Region2d *extsPtr,
+ int enclosed);
+
+static Tcl_FreeProc FreeMarker;
+
+typedef struct {
+ Blt_ConfigSpec *configSpecs; /* Marker configuration
+ * specifications */
+ MarkerConfigProc *configProc;
+ MarkerDrawProc *drawProc;
+ MarkerFreeProc *freeProc;
+ MarkerMapProc *mapProc;
+ MarkerPointProc *pointProc;
+ MarkerRegionProc *regionProc;
+ MarkerPostscriptProc *postscriptProc;
+
+} MarkerClass;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Marker --
+ *
+ * Structure defining the generic marker. In C++ parlance this would be
+ * the base class from which all markers are derived.
+ *
+ * This structure corresponds with the specific types of markers. Don't
+ * change this structure without changing the individual marker
+ * structures of each type below.
+ *
+ * --------------------------------------------------------------------------
+ */
+struct _Marker {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ Blt_HashEntry *hashPtr;
+
+ Blt_ChainLink link;
+
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+ Point2d *worldPts; /* Coordinate array to position
+ * marker */
+ int nWorldPts; /* Number of points in above array */
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+};
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BitmapMarker --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ Blt_HashEntry *hashPtr;
+
+ Blt_ChainLink link;
+
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+
+ Point2d *worldPts; /* Coordinate array to position
+ * marker. */
+ int nWorldPts; /* # of points in above array. */
+
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+
+ /* Fields specific to bitmap markers. */
+
+ Pixmap srcBitmap; /* Original bitmap. May be further
+ * scaled or rotated. */
+ float reqAngle; /* Requested rotation of the bitmap */
+ float angle; /* Normalized rotation (0..360
+ * degrees) */
+ Tk_Anchor anchor; /* If only one X-Y coordinate is given,
+ * indicates how to translate the given
+ * marker position. Otherwise, if there
+ * are two X-Y coordinates, then this
+ * value is ignored. */
+ Point2d anchorPt; /* Translated anchor point. */
+
+ XColor *outlineColor; /* Foreground color */
+ XColor *fillColor; /* Background color */
+
+ GC gc; /* Private graphic context */
+ GC fillGC; /* Shared graphic context */
+ Pixmap destBitmap; /* Bitmap to be drawn. */
+ int destWidth, destHeight; /* Dimensions of the final bitmap */
+
+ Point2d outline[MAX_OUTLINE_POINTS];/* Polygon representing the background
+ * of the bitmap. */
+ int nOutlinePts;
+} BitmapMarker;
+
+static Blt_ConfigSpec bitmapConfigSpecs[] =
+{
+ {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MARKER_ANCHOR,
+ Blt_Offset(BitmapMarker, anchor), 0},
+ {BLT_CONFIG_COLOR, "-background", "background", "Background",
+ DEF_MARKER_BACKGROUND, Blt_Offset(BitmapMarker, fillColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_BITMAP_TAGS,
+ Blt_Offset(BitmapMarker, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BITMAP, "-bitmap", "bitmap", "Bitmap", DEF_MARKER_BITMAP,
+ Blt_Offset(BitmapMarker, srcBitmap), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", DEF_MARKER_COORDS,
+ Blt_Offset(BitmapMarker, worldPts), BLT_CONFIG_NULL_OK,
+ &coordsOption},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", DEF_MARKER_ELEMENT,
+ Blt_Offset(BitmapMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_SYNONYM, "-fill", "background", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MARKER_FOREGROUND, Blt_Offset(BitmapMarker, outlineColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_MARKER_HIDE,
+ Blt_Offset(BitmapMarker, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_MARKER_MAP_X,
+ Blt_Offset(BitmapMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_MARKER_MAP_Y,
+ Blt_Offset(BitmapMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char *)NULL, (char *)NULL, DEF_MARKER_NAME,
+ Blt_Offset(BitmapMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_FLOAT, "-rotate", "rotate", "Rotate", DEF_MARKER_ANGLE,
+ Blt_Offset(BitmapMarker, reqAngle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_MARKER_STATE,
+ Blt_Offset(BitmapMarker, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", DEF_MARKER_UNDER,
+ Blt_Offset(BitmapMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", DEF_MARKER_X_OFFSET,
+ Blt_Offset(BitmapMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", DEF_MARKER_Y_OFFSET,
+ Blt_Offset(BitmapMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigureBitmapProc;
+static MarkerCreateProc CreateBitmapProc;
+static MarkerDrawProc DrawBitmapProc;
+static MarkerFreeProc FreeBitmapProc;
+static MarkerMapProc MapBitmapProc;
+static MarkerPointProc PointInBitmapProc;
+static MarkerPostscriptProc BitmapToPostscriptProc;
+static MarkerRegionProc RegionInBitmapProc;
+
+static MarkerClass bitmapMarkerClass = {
+ bitmapConfigSpecs,
+ ConfigureBitmapProc,
+ DrawBitmapProc,
+ FreeBitmapProc,
+ MapBitmapProc,
+ PointInBitmapProc,
+ RegionInBitmapProc,
+ BitmapToPostscriptProc,
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LineMarker --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ Blt_HashEntry *hashPtr;
+
+ Blt_ChainLink link;
+
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+
+ Point2d *worldPts; /* Coordinate array to position
+ * marker. */
+
+ int nWorldPts; /* Number of points in above array */
+
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+
+ XColor *fillColor;
+ XColor *outlineColor; /* Foreground and background colors */
+
+ int lineWidth; /* Line width. */
+ int capStyle; /* Cap style. */
+ int joinStyle; /* Join style.*/
+ Blt_Dashes dashes; /* Dash list values (max 11) */
+
+ GC gc; /* Private graphic context */
+
+ Segment2d *segments; /* Malloc'ed array of points.
+ * Represents individual line segments
+ * (2 points per segment) comprising the
+ * mapped line. The segments may not
+ * necessarily be connected after
+ * clipping. */
+ int nSegments; /* # segments in the above array. */
+ int xor;
+ int xorState; /* State of the XOR drawing. Indicates
+ * if the marker is currently drawn. */
+} LineMarker;
+
+static Blt_ConfigSpec lineConfigSpecs[] =
+{
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_LINE_TAGS,
+ Blt_Offset(LineMarker, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CAP_STYLE, "-cap", "cap", "Cap", DEF_MARKER_CAP_STYLE,
+ Blt_Offset(LineMarker, capStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", DEF_MARKER_COORDS,
+ Blt_Offset(LineMarker, worldPts), BLT_CONFIG_NULL_OK, &coordsOption},
+ {BLT_CONFIG_DASHES, "-dashes", "dashes", "Dashes", DEF_MARKER_DASHES,
+ Blt_Offset(LineMarker, dashes), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_NNEG, "-dashoffset", "dashOffset", "DashOffset",
+ DEF_MARKER_DASH_OFFSET, Blt_Offset(LineMarker, dashes.offset),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", DEF_MARKER_ELEMENT,
+ Blt_Offset(LineMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-fill", "fill", "Fill", (char *)NULL,
+ Blt_Offset(LineMarker, fillColor), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_JOIN_STYLE, "-join", "join", "Join", DEF_MARKER_JOIN_STYLE,
+ Blt_Offset(LineMarker, joinStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "LineWidth",
+ DEF_MARKER_LINE_WIDTH, Blt_Offset(LineMarker, lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_MARKER_HIDE,
+ Blt_Offset(LineMarker, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_MARKER_MAP_X,
+ Blt_Offset(LineMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_MARKER_MAP_Y,
+ Blt_Offset(LineMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char *)NULL, (char *)NULL, DEF_MARKER_NAME,
+ Blt_Offset(LineMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_COLOR, "-outline", "outline", "Outline",
+ DEF_MARKER_OUTLINE_COLOR, Blt_Offset(LineMarker, outlineColor),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_MARKER_STATE,
+ Blt_Offset(LineMarker, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", DEF_MARKER_UNDER,
+ Blt_Offset(LineMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", DEF_MARKER_X_OFFSET,
+ Blt_Offset(LineMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-xor", "xor", "Xor", DEF_MARKER_XOR,
+ Blt_Offset(LineMarker, xor), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", DEF_MARKER_Y_OFFSET,
+ Blt_Offset(LineMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigureLineProc;
+static MarkerCreateProc CreateLineProc;
+static MarkerDrawProc DrawLineProc;
+static MarkerFreeProc FreeLineProc;
+static MarkerMapProc MapLineProc;
+static MarkerPointProc PointInLineProc;
+static MarkerPostscriptProc LineToPostscriptProc;
+static MarkerRegionProc RegionInLineProc;
+
+static MarkerClass lineMarkerClass = {
+ lineConfigSpecs,
+ ConfigureLineProc,
+ DrawLineProc,
+ FreeLineProc,
+ MapLineProc,
+ PointInLineProc,
+ RegionInLineProc,
+ LineToPostscriptProc,
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PolygonMarker --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ Blt_HashEntry *hashPtr;
+
+ Blt_ChainLink link;
+
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+
+ Point2d *worldPts; /* Coordinate array to position
+ * marker. */
+
+ int nWorldPts; /* Number of points in above array */
+
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+
+ Point2d *screenPts; /* Array of points representing the
+ * polygon in screen coordinates. It's
+ * not used for drawing, but to generate
+ * the outlinePts and fillPts arrays
+ * that are the coordinates of the
+ * possibly clipped outline and filled
+ * polygon. */
+
+ ColorPair outline;
+ ColorPair fill;
+
+ Pixmap stipple; /* Stipple pattern to fill the
+ * polygon. */
+ int lineWidth; /* Width of polygon outline. */
+ int capStyle;
+ int joinStyle;
+ Blt_Dashes dashes; /* List of dash values. Indicates how
+ * to draw the dashed line. If no dash
+ * values are provided, or the first
+ * value is zero, then the line is drawn
+ * solid. */
+
+ GC outlineGC; /* Graphics context to draw the outline
+ * of the polygon. */
+ GC fillGC; /* Graphics context to draw the filled
+ * polygon. */
+
+ Point2d *fillPts; /* Malloc'ed array of points used to
+ * draw the filled polygon. These points
+ * may form a degenerate polygon after
+ * clipping. */
+ int nFillPts; /* # points in the above array. */
+ Segment2d *outlinePts; /* Malloc'ed array of points.
+ * Represents individual line segments
+ * (2 points per segment) comprising the
+ * outline of the polygon. The segments
+ * may not necessarily be closed or
+ * connected after clipping. */
+ int nOutlinePts; /* # points in the above array. */
+ int xor;
+ int xorState; /* State of the XOR drawing. Indicates
+ * if the marker is visible. We have to
+ * drawn it again to erase it. */
+} PolygonMarker;
+
+static Blt_ConfigSpec polygonConfigSpecs[] =
+{
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_POLYGON_TAGS,
+ Blt_Offset(PolygonMarker, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CAP_STYLE, "-cap", "cap", "Cap", DEF_MARKER_CAP_STYLE,
+ Blt_Offset(PolygonMarker, capStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", DEF_MARKER_COORDS,
+ Blt_Offset(PolygonMarker, worldPts), BLT_CONFIG_NULL_OK, &coordsOption},
+ {BLT_CONFIG_DASHES, "-dashes", "dashes", "Dashes", DEF_MARKER_DASHES,
+ Blt_Offset(PolygonMarker, dashes), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", DEF_MARKER_ELEMENT,
+ Blt_Offset(PolygonMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-fill", "fill", "Fill", DEF_MARKER_FILL_COLOR,
+ Blt_Offset(PolygonMarker, fill), BLT_CONFIG_NULL_OK, &colorPairOption},
+ {BLT_CONFIG_JOIN_STYLE, "-join", "join", "Join", DEF_MARKER_JOIN_STYLE,
+ Blt_Offset(PolygonMarker, joinStyle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-linewidth", "lineWidth", "LineWidth",
+ DEF_MARKER_LINE_WIDTH, Blt_Offset(PolygonMarker, lineWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_MARKER_HIDE,
+ Blt_Offset(PolygonMarker, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_MARKER_MAP_X,
+ Blt_Offset(PolygonMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_MARKER_MAP_Y,
+ Blt_Offset(PolygonMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char *)NULL, (char *)NULL, DEF_MARKER_NAME,
+ Blt_Offset(PolygonMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-outline", "outline", "Outline",
+ DEF_MARKER_OUTLINE_COLOR, Blt_Offset(PolygonMarker, outline),
+ BLT_CONFIG_NULL_OK, &colorPairOption},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_MARKER_STATE,
+ Blt_Offset(PolygonMarker, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMAP, "-stipple", "stipple", "Stipple", DEF_MARKER_STIPPLE,
+ Blt_Offset(PolygonMarker, stipple), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", DEF_MARKER_UNDER,
+ Blt_Offset(PolygonMarker, drawUnder),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", DEF_MARKER_X_OFFSET,
+ Blt_Offset(PolygonMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-xor", "xor", "Xor", DEF_MARKER_XOR,
+ Blt_Offset(PolygonMarker, xor), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", DEF_MARKER_Y_OFFSET,
+ Blt_Offset(PolygonMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigurePolygonProc;
+static MarkerCreateProc CreatePolygonProc;
+static MarkerDrawProc DrawPolygonProc;
+static MarkerFreeProc FreePolygonProc;
+static MarkerMapProc MapPolygonProc;
+static MarkerPointProc PointInPolygonProc;
+static MarkerPostscriptProc PolygonToPostscriptProc;
+static MarkerRegionProc RegionInPolygonProc;
+
+static MarkerClass polygonMarkerClass = {
+ polygonConfigSpecs,
+ ConfigurePolygonProc,
+ DrawPolygonProc,
+ FreePolygonProc,
+ MapPolygonProc,
+ PointInPolygonProc,
+ RegionInPolygonProc,
+ PolygonToPostscriptProc,
+};
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TextMarker --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+ MarkerClass *classPtr;
+ Blt_HashEntry *hashPtr;
+ Blt_ChainLink link;
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+ Point2d *worldPts; /* Coordinate array to position
+ * marker. */
+ int nWorldPts; /* # of points in above array */
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+ int state;
+
+ /* Fields specific to text markers. */
+ const char *string; /* Text string to be display. The
+ * string make contain newlines. */
+ Tk_Anchor anchor; /* Indicates how to translate the given
+ * marker position. */
+ Point2d anchorPt; /* Translated anchor point. */
+ int width, height; /* Dimension of bounding box. */
+ TextStyle style; /* Text attributes (font, fg, anchor,
+ * etc) */
+ Point2d outline[5];
+ XColor *fillColor;
+ GC fillGC;
+} TextMarker;
+
+
+static Blt_ConfigSpec textConfigSpecs[] =
+{
+ {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MARKER_ANCHOR,
+ Blt_Offset(TextMarker, anchor), 0},
+ {BLT_CONFIG_COLOR, "-background", "background", "MarkerBackground",
+ (char *)NULL, Blt_Offset(TextMarker, fillColor), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", "Background", (char *)NULL, 0, 0},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_TEXT_TAGS,
+ Blt_Offset(TextMarker, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", DEF_MARKER_COORDS,
+ Blt_Offset(TextMarker, worldPts), BLT_CONFIG_NULL_OK,
+ &coordsOption},
+ {BLT_CONFIG_STRING, "-element", "element", "Element",
+ DEF_MARKER_ELEMENT, Blt_Offset(TextMarker, elemName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", "Foreground", (char *)NULL, 0, 0},
+ {BLT_CONFIG_SYNONYM, "-fill", "background", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_FONT, "-font", "font", "Font", DEF_MARKER_FONT,
+ Blt_Offset(TextMarker, style.font), 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_MARKER_FOREGROUND, Blt_Offset(TextMarker, style.color), 0},
+ {BLT_CONFIG_JUSTIFY, "-justify", "justify", "Justify",
+ DEF_MARKER_JUSTIFY, Blt_Offset(TextMarker, style.justify),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_MARKER_HIDE,
+ Blt_Offset(TextMarker, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_MARKER_MAP_X,
+ Blt_Offset(TextMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_MARKER_MAP_Y,
+ Blt_Offset(TextMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char *)NULL, (char *)NULL, DEF_MARKER_NAME,
+ Blt_Offset(TextMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-outline", "foreground", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_PAD, "-padx", "padX", "PadX", DEF_MARKER_PAD,
+ Blt_Offset(TextMarker, style.xPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PAD, "-pady", "padY", "PadY", DEF_MARKER_PAD,
+ Blt_Offset(TextMarker, style.yPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_FLOAT, "-rotate", "rotate", "Rotate", DEF_MARKER_ANGLE,
+ Blt_Offset(TextMarker, style.angle), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_MARKER_STATE,
+ Blt_Offset(TextMarker, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-text", "text", "Text", DEF_MARKER_TEXT,
+ Blt_Offset(TextMarker, string), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", DEF_MARKER_UNDER,
+ Blt_Offset(TextMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", DEF_MARKER_X_OFFSET,
+ Blt_Offset(TextMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", DEF_MARKER_Y_OFFSET,
+ Blt_Offset(TextMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigureTextProc;
+static MarkerCreateProc CreateTextProc;
+static MarkerDrawProc DrawTextProc;
+static MarkerFreeProc FreeTextProc;
+static MarkerMapProc MapTextProc;
+static MarkerPointProc PointInTextProc;
+static MarkerPostscriptProc TextToPostscriptProc;
+static MarkerRegionProc RegionInTextProc;
+
+static MarkerClass textMarkerClass = {
+ textConfigSpecs,
+ ConfigureTextProc,
+ DrawTextProc,
+ FreeTextProc,
+ MapTextProc,
+ PointInTextProc,
+ RegionInTextProc,
+ TextToPostscriptProc,
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * WindowMarker --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ GraphObj obj; /* Must be first field in marker. */
+
+ MarkerClass *classPtr;
+
+ Blt_HashEntry *hashPtr;
+
+ Blt_ChainLink link;
+
+ const char *elemName; /* Element associated with marker. Let's
+ * you link a marker to an element. The
+ * marker is drawn only if the element
+ * is also visible. */
+ Axis2d axes;
+
+ Point2d *worldPts; /* Coordinate array to position
+ * marker */
+
+ int nWorldPts; /* # of points in above array */
+
+ int drawUnder; /* If non-zero, draw the marker
+ * underneath any elements. This can be
+ * a performance penalty because the
+ * graph must be redraw entirely each
+ * time the marker is redrawn. */
+
+ int clipped; /* Indicates if the marker is totally
+ * clipped by the plotting area. */
+
+ unsigned int flags;
+
+
+ int xOffset, yOffset; /* Pixel offset from graph position */
+
+ int state;
+
+ /* Fields specific to window markers. */
+
+ const char *childName; /* Name of child widget. */
+ Tk_Window child; /* Window to display. */
+ int reqWidth, reqHeight; /* If non-zero, this overrides the size
+ * requested by the child widget. */
+
+ Tk_Anchor anchor; /* Indicates how to translate the given
+ * marker position. */
+
+ Point2d anchorPt; /* Translated anchor point. */
+ int width, height; /* Current size of the child window. */
+
+} WindowMarker;
+
+static Blt_ConfigSpec windowConfigSpecs[] =
+{
+ {BLT_CONFIG_ANCHOR, "-anchor", "anchor", "Anchor", DEF_MARKER_ANCHOR,
+ Blt_Offset(WindowMarker, anchor), 0},
+ {BLT_CONFIG_LIST, "-bindtags", "bindTags", "BindTags", DEF_WINDOW_TAGS,
+ Blt_Offset(WindowMarker, obj.tags), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_CUSTOM, "-coords", "coords", "Coords", DEF_MARKER_COORDS,
+ Blt_Offset(WindowMarker, worldPts), BLT_CONFIG_NULL_OK,
+ &coordsOption},
+ {BLT_CONFIG_STRING, "-element", "element", "Element", DEF_MARKER_ELEMENT,
+ Blt_Offset(WindowMarker, elemName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_POS, "-height", "height", "Height", DEF_MARKER_HEIGHT,
+ Blt_Offset(WindowMarker, reqHeight), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-hide", "hide", "Hide", DEF_MARKER_HIDE,
+ Blt_Offset(WindowMarker, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)HIDE},
+ {BLT_CONFIG_CUSTOM, "-mapx", "mapX", "MapX", DEF_MARKER_MAP_X,
+ Blt_Offset(WindowMarker, axes.x), 0, &bltXAxisOption},
+ {BLT_CONFIG_CUSTOM, "-mapy", "mapY", "MapY", DEF_MARKER_MAP_Y,
+ Blt_Offset(WindowMarker, axes.y), 0, &bltYAxisOption},
+ {BLT_CONFIG_STRING, "-name", (char *)NULL, (char *)NULL, DEF_MARKER_NAME,
+ Blt_Offset(WindowMarker, obj.name), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STATE, "-state", "state", "State", DEF_MARKER_STATE,
+ Blt_Offset(WindowMarker, state), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-under", "under", "Under", DEF_MARKER_UNDER,
+ Blt_Offset(WindowMarker, drawUnder), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_POS, "-width", "width", "Width", DEF_MARKER_WIDTH,
+ Blt_Offset(WindowMarker, reqWidth), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-window", "window", "Window", DEF_MARKER_WINDOW,
+ Blt_Offset(WindowMarker, childName), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS, "-xoffset", "xOffset", "XOffset", DEF_MARKER_X_OFFSET,
+ Blt_Offset(WindowMarker, xOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS, "-yoffset", "yOffset", "YOffset", DEF_MARKER_Y_OFFSET,
+ Blt_Offset(WindowMarker, yOffset), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static MarkerConfigProc ConfigureWindowProc;
+static MarkerCreateProc CreateWindowProc;
+static MarkerDrawProc DrawWindowProc;
+static MarkerFreeProc FreeWindowProc;
+static MarkerMapProc MapWindowProc;
+static MarkerPointProc PointInWindowProc;
+static MarkerPostscriptProc WindowToPostscriptProc;
+static MarkerRegionProc RegionInWindowProc;
+
+static MarkerClass windowMarkerClass = {
+ windowConfigSpecs,
+ ConfigureWindowProc,
+ DrawWindowProc,
+ FreeWindowProc,
+ MapWindowProc,
+ PointInWindowProc,
+ RegionInWindowProc,
+ WindowToPostscriptProc,
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BoxesDontOverlap --
+ *
+ * Tests if the bounding box of a marker overlaps the plotting area in
+ * any way. If so, the marker will be drawn. Just do a min/max test on
+ * the extents of both boxes.
+ *
+ * Note: It's assumed that the extents of the bounding box lie
+ * within the area. So for a 10x10 rectangle, bottom and
+ * left would be 9.
+ *
+ * Results:
+ * Returns 0 is the marker is visible in the plotting area, and 1
+ * otherwise (marker is clipped).
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+BoxesDontOverlap(Graph *graphPtr, Region2d *extsPtr)
+{
+ assert(extsPtr->right >= extsPtr->left);
+ assert(extsPtr->bottom >= extsPtr->top);
+ assert(graphPtr->right >= graphPtr->left);
+ assert(graphPtr->bottom >= graphPtr->top);
+
+ return (((double)graphPtr->right < extsPtr->left) ||
+ ((double)graphPtr->bottom < extsPtr->top) ||
+ (extsPtr->right < (double)graphPtr->left) ||
+ (extsPtr->bottom < (double)graphPtr->top));
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetCoordinate --
+ *
+ * Convert the expression string into a floating point value. The * only
+ * reason we use this routine instead of Blt_ExprDouble is to * handle
+ * "elastic" bounds. That is, convert the strings "-Inf", * "Inf" into
+ * -(DBL_MAX) and DBL_MAX respectively.
+ *
+ * Results:
+ * The return value is a standard TCL result. The value of the
+ * expression is passed back via valuePtr.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+GetCoordinate(
+ Tcl_Interp *interp, /* Interpreter to return results */
+ Tcl_Obj *objPtr, /* Numeric expression string to
+ * parse */
+ double *valuePtr) /* Real-valued result of expression */
+{
+ char c;
+ const char *expr;
+
+ expr = Tcl_GetString(objPtr);
+ c = expr[0];
+ if ((c == 'I') && (strcmp(expr, "Inf") == 0)) {
+ *valuePtr = DBL_MAX; /* Elastic upper bound */
+ } else if ((c == '-') && (expr[1] == 'I') && (strcmp(expr, "-Inf") == 0)) {
+ *valuePtr = -DBL_MAX; /* Elastic lower bound */
+ } else if ((c == '+') && (expr[1] == 'I') && (strcmp(expr, "+Inf") == 0)) {
+ *valuePtr = DBL_MAX; /* Elastic upper bound */
+ } else if (Blt_ExprDoubleFromObj(interp, objPtr, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PrintCoordinate --
+ *
+ * Convert the floating point value into its string representation. The
+ * only reason this routine is used in instead of sprintf, is to handle
+ * the "elastic" bounds. That is, convert the values DBL_MAX and
+ * -(DBL_MAX) into "+Inf" and "-Inf" respectively.
+ *
+ * Results:
+ * The return value is a standard TCL result. The string of the *
+ * expression is passed back via string.
+ *
+ * -------------------------------------------------------------------------- */
+static Tcl_Obj *
+PrintCoordinate(double x)
+{
+ if (x == DBL_MAX) {
+ return Tcl_NewStringObj("+Inf", -1);
+ } else if (x == -DBL_MAX) {
+ return Tcl_NewStringObj("-Inf", -1);
+ } else {
+ return Tcl_NewDoubleObj(x);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ParseCoordinates --
+ *
+ * The TCL coordinate list is converted to their floating point
+ * values. It will then replace the current marker coordinates.
+ *
+ * Since different marker types require different number of coordinates
+ * this must be checked here.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side effects:
+ * If the marker coordinates are reset, the graph is eventually redrawn
+ * with at the new marker coordinates.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ParseCoordinates(
+ Tcl_Interp *interp,
+ Marker *markerPtr,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ int nWorldPts;
+ int minArgs, maxArgs;
+ Point2d *worldPts;
+ int i;
+
+ if (objc == 0) {
+ return TCL_OK;
+ }
+ if (objc & 1) {
+ Tcl_AppendResult(interp, "odd number of marker coordinates specified",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ switch (markerPtr->obj.classId) {
+ case CID_MARKER_LINE:
+ minArgs = 4, maxArgs = 0;
+ break;
+ case CID_MARKER_POLYGON:
+ minArgs = 6, maxArgs = 0;
+ break;
+ case CID_MARKER_WINDOW:
+ case CID_MARKER_TEXT:
+ minArgs = 2, maxArgs = 2;
+ break;
+ case CID_MARKER_IMAGE:
+ case CID_MARKER_BITMAP:
+ minArgs = 2, maxArgs = 4;
+ break;
+ default:
+ Tcl_AppendResult(interp, "unknown marker type", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc < minArgs) {
+ Tcl_AppendResult(interp, "too few marker coordinates specified",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if ((maxArgs > 0) && (objc > maxArgs)) {
+ Tcl_AppendResult(interp, "too many marker coordinates specified",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ nWorldPts = objc / 2;
+ worldPts = malloc(nWorldPts * sizeof(Point2d));
+ if (worldPts == NULL) {
+ Tcl_AppendResult(interp, "can't allocate new coordinate array",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ {
+ Point2d *pp;
+
+ pp = worldPts;
+ for (i = 0; i < objc; i += 2) {
+ double x, y;
+
+ if ((GetCoordinate(interp, objv[i], &x) != TCL_OK) ||
+ (GetCoordinate(interp, objv[i + 1], &y) != TCL_OK)) {
+ free(worldPts);
+ return TCL_ERROR;
+ }
+ pp->x = x, pp->y = y, pp++;
+ }
+ }
+ /* Don't free the old coordinate array until we've parsed the new
+ * coordinates without errors. */
+ if (markerPtr->worldPts != NULL) {
+ free(markerPtr->worldPts);
+ }
+ markerPtr->worldPts = worldPts;
+ markerPtr->nWorldPts = nWorldPts;
+ markerPtr->flags |= MAP_ITEM;
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static void
+FreeCoordsProc(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Marker *markerPtr = (Marker *)widgRec;
+ Point2d **pointsPtr = (Point2d **)(widgRec + offset);
+
+ if (*pointsPtr != NULL) {
+ free(*pointsPtr);
+ *pointsPtr = NULL;
+ }
+ markerPtr->nWorldPts = 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToCoordsProc --
+ *
+ * Given a TCL list of numeric expression representing the element
+ * values, convert into an array of floating point values. In addition,
+ * the minimum and maximum values are saved. Since elastic values are
+ * allow (values which translate to the min/max of the graph), we must
+ * try to get the non-elastic minimum and maximum.
+ *
+ * Results:
+ * The return value is a standard TCL result. The vector is
+ * passed back via the vecPtr.
+ *
+ * --------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToCoordsProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to return results */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* TCL list of numeric expressions */
+ char *widgRec, /* Marker record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Marker *markerPtr = (Marker *)widgRec;
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc == 0) {
+ return TCL_OK;
+ }
+ return ParseCoordinates(interp, markerPtr, objc, objv);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CoordsToObjProc --
+ *
+ * Convert the vector of floating point values into a TCL list.
+ *
+ * Results:
+ * The string representation of the vector is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+CoordsToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Marker record */
+ int offset, /* Not used. */
+ int flags) /* Not used. */
+{
+ Marker *markerPtr = (Marker *)widgRec;
+ Tcl_Obj *listObjPtr;
+ Point2d *pp, *pend;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (pp = markerPtr->worldPts, pend = pp + markerPtr->nWorldPts; pp < pend;
+ pp++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, PrintCoordinate(pp->x));
+ Tcl_ListObjAppendElement(interp, listObjPtr, PrintCoordinate(pp->y));
+ }
+ return listObjPtr;
+}
+
+/*LINTLIBRARY*/
+static int
+GetColorPair(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj *fgObjPtr, Tcl_Obj *bgObjPtr,
+ ColorPair *pairPtr,
+ int allowDefault)
+{
+ XColor *fgColor, *bgColor;
+ const char *string;
+
+ fgColor = bgColor = NULL;
+ if (fgObjPtr != NULL) {
+ int length;
+
+ string = Tcl_GetStringFromObj(fgObjPtr, &length);
+ if (string[0] == '\0') {
+ fgColor = NULL;
+ } else if ((allowDefault) && (string[0] == 'd') &&
+ (strncmp(string, "defcolor", length) == 0)) {
+ fgColor = COLOR_DEFAULT;
+ } else {
+ fgColor = Tk_AllocColorFromObj(interp, tkwin, fgObjPtr);
+ if (fgColor == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (bgObjPtr != NULL) {
+ int length;
+
+ string = Tcl_GetStringFromObj(bgObjPtr, &length);
+ if (string[0] == '\0') {
+ bgColor = NULL;
+ } else if ((allowDefault) && (string[0] == 'd') &&
+ (strncmp(string, "defcolor", length) == 0)) {
+ bgColor = COLOR_DEFAULT;
+ } else {
+ bgColor = Tk_AllocColorFromObj(interp, tkwin, bgObjPtr);
+ if (bgColor == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (pairPtr->fgColor != NULL) {
+ Tk_FreeColor(pairPtr->fgColor);
+ }
+ if (pairPtr->bgColor != NULL) {
+ Tk_FreeColor(pairPtr->bgColor);
+ }
+ pairPtr->fgColor = fgColor;
+ pairPtr->bgColor = bgColor;
+ return TCL_OK;
+}
+
+void
+Blt_FreeColorPair(ColorPair *pairPtr)
+{
+ if ((pairPtr->bgColor != NULL) && (pairPtr->bgColor != COLOR_DEFAULT)) {
+ Tk_FreeColor(pairPtr->bgColor);
+ }
+ if ((pairPtr->fgColor != NULL) && (pairPtr->fgColor != COLOR_DEFAULT)) {
+ Tk_FreeColor(pairPtr->fgColor);
+ }
+ pairPtr->bgColor = pairPtr->fgColor = NULL;
+}
+
+static void
+FreeColorPairProc(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ ColorPair *pairPtr = (ColorPair *)(widgRec + offset);
+
+ Blt_FreeColorPair(pairPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToColorPairProc --
+ *
+ * Convert the color names into pair of XColor pointers.
+ *
+ * Results:
+ * A standard TCL result. The color pointer is written into the
+ * widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToColorPairProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to return results */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing color */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ ColorPair *pairPtr = (ColorPair *)(widgRec + offset);
+ long longValue = (long)clientData;
+ int bool;
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "too many names in colors list",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 0) {
+ Blt_FreeColorPair(pairPtr);
+ return TCL_OK;
+ }
+ bool = (int)longValue;
+ if (objc == 1) {
+ if (GetColorPair(interp, tkwin, objv[0], NULL, pairPtr, bool)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ if (GetColorPair(interp, tkwin, objv[0], objv[1], pairPtr, bool)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NameOfColor --
+ *
+ * Convert the color option value into a string.
+ *
+ * Results:
+ * The static string representing the color option is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static const char *
+NameOfColor(XColor *colorPtr)
+{
+ if (colorPtr == NULL) {
+ return "";
+ } else if (colorPtr == COLOR_DEFAULT) {
+ return "defcolor";
+ } else {
+ return Tk_NameOfColor(colorPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ColorPairToObjProc --
+ *
+ * Convert the color pairs into color names.
+ *
+ * Results:
+ * The string representing the symbol color is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ColorPairToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Element information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ ColorPair *pairPtr = (ColorPair *)(widgRec + offset);
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(NameOfColor(pairPtr->fgColor), -1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(NameOfColor(pairPtr->bgColor), -1));
+ return listObjPtr;
+}
+
+static INLINE int
+IsElementHidden(Marker *markerPtr)
+{
+ Blt_HashEntry *hPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ /* Look up the named element and see if it's hidden */
+ hPtr = Blt_FindHashEntry(&graphPtr->elements.table, markerPtr->elemName);
+ if (hPtr != NULL) {
+ Element *elemPtr;
+
+ elemPtr = Blt_GetHashValue(hPtr);
+ if ((elemPtr->link == NULL) || (elemPtr->flags & HIDE)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HMap --
+ *
+ * Maps the given graph coordinate value to its axis, returning a window
+ * position. This is a slight variation on the normal Blt_HMap routine.
+ * It treats -Inf as the minimum axis value and Inf as the maximum.
+ *
+ * Results:
+ * Returns a floating point number representing the window coordinate
+ * position on the given axis.
+ *
+ * --------------------------------------------------------------------------
+ */
+static double
+HMap(Axis *axisPtr, double x)
+{
+ if (x == DBL_MAX) {
+ x = 1.0;
+ } else if (x == -DBL_MAX) {
+ x = 0.0;
+ } else {
+ if (axisPtr->logScale) {
+ if (x > 0.0) {
+ x = log10(x);
+ } else if (x < 0.0) {
+ x = 0.0;
+ }
+ }
+ x = NORMALIZE(axisPtr, x);
+ }
+ if (axisPtr->descending) {
+ x = 1.0 - x;
+ }
+ /* Horizontal transformation */
+ return (x * axisPtr->screenRange + axisPtr->screenMin);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VMap --
+ *
+ * Map the given graph coordinate value to its axis, returning a window
+ * position. This is a slight variation on the normal Blt_VMap routine.
+ * It treats -Inf as the minimum axis value and Inf as the maximum.
+ *
+ * Results:
+ * Returns a double precision number representing the window coordinate
+ * position on the given axis.
+ *
+ *---------------------------------------------------------------------------
+ */
+static double
+VMap(Axis *axisPtr, double y)
+{
+ if (y == DBL_MAX) {
+ y = 1.0;
+ } else if (y == -DBL_MAX) {
+ y = 0.0;
+ } else {
+ if (axisPtr->logScale) {
+ if (y > 0.0) {
+ y = log10(y);
+ } else if (y < 0.0) {
+ y = 0.0;
+ }
+ }
+ y = NORMALIZE(axisPtr, y);
+ }
+ if (axisPtr->descending) {
+ y = 1.0 - y;
+ }
+ /* Vertical transformation. */
+ return (((1.0 - y) * axisPtr->screenRange) + axisPtr->screenMin);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapPoint --
+ *
+ * Maps the given graph x,y coordinate values to a window position.
+ *
+ * Results:
+ * Returns a XPoint structure containing the window coordinates of the
+ * given graph x,y coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Point2d
+MapPoint(
+ Point2d *pointPtr, /* Graph X-Y coordinate. */
+ Axis2d *axesPtr) /* Specifies which axes to use */
+{
+ Point2d result;
+ Graph *graphPtr = axesPtr->y->obj.graphPtr;
+
+ if (graphPtr->inverted) {
+ result.x = HMap(axesPtr->y, pointPtr->y);
+ result.y = VMap(axesPtr->x, pointPtr->x);
+ } else {
+ result.x = HMap(axesPtr->x, pointPtr->x);
+ result.y = VMap(axesPtr->y, pointPtr->y);
+ }
+ return result; /* Result is screen coordinate. */
+}
+
+static Marker *
+CreateMarker(
+ Graph *graphPtr,
+ const char *name,
+ ClassId classId)
+{
+ Marker *markerPtr;
+
+ /* Create the new marker based upon the given type */
+ switch (classId) {
+ case CID_MARKER_BITMAP:
+ markerPtr = CreateBitmapProc(); /* bitmap */
+ break;
+ case CID_MARKER_LINE:
+ markerPtr = CreateLineProc(); /* line */
+ break;
+ case CID_MARKER_IMAGE:
+ return NULL; /* not supported */
+ break;
+ case CID_MARKER_TEXT:
+ markerPtr = CreateTextProc(); /* text */
+ break;
+ case CID_MARKER_POLYGON:
+ markerPtr = CreatePolygonProc(); /* polygon */
+ break;
+ case CID_MARKER_WINDOW:
+ markerPtr = CreateWindowProc(); /* window */
+ break;
+ default:
+ return NULL;
+ }
+ markerPtr->obj.graphPtr = graphPtr;
+ markerPtr->drawUnder = FALSE;
+ markerPtr->flags |= MAP_ITEM;
+ markerPtr->obj.name = Blt_Strdup(name);
+ Blt_GraphSetObjectClass(&markerPtr->obj, classId);
+ return markerPtr;
+}
+
+
+static void
+DestroyMarker(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ if (markerPtr->drawUnder) {
+ /* If the marker to be deleted is currently displayed below the
+ * elements, then backing store needs to be repaired. */
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ /*
+ * Call the marker's type-specific deallocation routine. We do it first
+ * while all the marker fields are still valid.
+ */
+ (*markerPtr->classPtr->freeProc)(markerPtr);
+
+ /* Dump any bindings that might be registered for the marker. */
+ Blt_DeleteBindings(graphPtr->bindTable, markerPtr);
+
+ /* Release all the X resources associated with the marker. */
+ Blt_FreeOptions(markerPtr->classPtr->configSpecs, (char *)markerPtr,
+ graphPtr->display, 0);
+
+ if (markerPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&graphPtr->markers.table,
+ markerPtr->hashPtr);
+ }
+ if (markerPtr->link != NULL) {
+ Blt_Chain_DeleteLink(graphPtr->markers.displayList, markerPtr->link);
+ }
+ if (markerPtr->obj.name != NULL) {
+ free((void*)(markerPtr->obj.name));
+ }
+ free(markerPtr);
+}
+
+static void FreeMarker(char* dataPtr)
+{
+ Marker *markerPtr = (Marker *)dataPtr;
+ DestroyMarker(markerPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureBitmapProc --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a bitmap
+ * marker.
+ *
+ * Results:
+ * A standard TCL result. If TCL_ERROR is returned, then interp->result
+ * contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as bitmap pixmap, colors, rotation,
+ * etc. get set for markerPtr; old resources get freed, if there were
+ * any. The marker is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ConfigureBitmapProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+
+ if (bmPtr->srcBitmap == None) {
+ return TCL_OK;
+ }
+ bmPtr->angle = fmod(bmPtr->reqAngle, 360.0);
+ if (bmPtr->angle < 0.0) {
+ bmPtr->angle += 360.0;
+ }
+ gcMask = 0;
+
+ if (bmPtr->outlineColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = bmPtr->outlineColor->pixel;
+ }
+
+ if (bmPtr->fillColor != NULL) {
+ /* Opaque bitmap: both foreground and background (fill) colors
+ * are used. */
+ gcValues.background = bmPtr->fillColor->pixel;
+ gcMask |= GCBackground;
+ } else {
+ /* Transparent bitmap: set the clip mask to the current bitmap. */
+ gcValues.clip_mask = bmPtr->srcBitmap;
+ gcMask |= GCClipMask;
+ }
+
+ /*
+ * This is technically a shared GC, but we're going to set/change the clip
+ * origin anyways before we draw the bitmap. This relies on the fact that
+ * no other client will be allocated this GC with the GCClipMask set to
+ * this particular bitmap.
+ */
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (bmPtr->gc != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->gc);
+ }
+ bmPtr->gc = newGC;
+
+ /* Create the background GC containing the fill color. */
+
+ if (bmPtr->fillColor != NULL) {
+ gcValues.foreground = bmPtr->fillColor->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (bmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
+ }
+ bmPtr->fillGC = newGC;
+ }
+
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapBitmapProc --
+ *
+ * This procedure gets called each time the layout of the graph changes.
+ * The x, y window coordinates of the bitmap marker are saved in the
+ * marker structure.
+ *
+ * Additionly, if no background color was specified, the
+ * GCTileStipXOrigin and GCTileStipYOrigin attributes are set in the
+ * private GC.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Window coordinates are saved and if no background color was set, the
+ * GC stipple origins are changed to calculated window coordinates.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapBitmapProc(Marker *markerPtr)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ Region2d extents;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ Point2d anchorPt;
+ Point2d corner1, corner2;
+ int destWidth, destHeight;
+ int srcWidth, srcHeight;
+ int i;
+
+ if (bmPtr->srcBitmap == None) {
+ return;
+ }
+ if (bmPtr->destBitmap != None) {
+ Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap);
+ bmPtr->destBitmap = None;
+ }
+ /*
+ * Collect the coordinates. The number of coordinates will determine the
+ * calculations to be made.
+ *
+ * x1 y1 A single pair of X-Y coordinates. They represent
+ * the anchor position of the bitmap.
+ *
+ * x1 y1 x2 y2 Two pairs of X-Y coordinates. They represent
+ * two opposite corners of a bounding rectangle. The
+ * bitmap is possibly rotated and scaled to fit into
+ * this box.
+ *
+ */
+ Tk_SizeOfBitmap(graphPtr->display, bmPtr->srcBitmap, &srcWidth,
+ &srcHeight);
+ corner1 = MapPoint(markerPtr->worldPts, &markerPtr->axes);
+ if (markerPtr->nWorldPts > 1) {
+ double hold;
+
+ corner2 = MapPoint(markerPtr->worldPts + 1, &markerPtr->axes);
+ /* Flip the corners if necessary */
+ if (corner1.x > corner2.x) {
+ hold = corner1.x, corner1.x = corner2.x, corner2.x = hold;
+ }
+ if (corner1.y > corner2.y) {
+ hold = corner1.y, corner1.y = corner2.y, corner2.y = hold;
+ }
+ } else {
+ corner2.x = corner1.x + srcWidth - 1;
+ corner2.y = corner1.y + srcHeight - 1;
+ }
+ destWidth = (int)(corner2.x - corner1.x) + 1;
+ destHeight = (int)(corner2.y - corner1.y) + 1;
+
+ if (markerPtr->nWorldPts == 1) {
+ anchorPt = Blt_AnchorPoint(corner1.x, corner1.y, (double)destWidth,
+ (double)destHeight, bmPtr->anchor);
+ } else {
+ anchorPt = corner1;
+ }
+ anchorPt.x += markerPtr->xOffset;
+ anchorPt.y += markerPtr->yOffset;
+
+ /* Check if the bitmap sits at least partially in the plot area. */
+ extents.left = anchorPt.x;
+ extents.top = anchorPt.y;
+ extents.right = anchorPt.x + destWidth - 1;
+ extents.bottom = anchorPt.y + destHeight - 1;
+ markerPtr->clipped = BoxesDontOverlap(graphPtr, &extents);
+ if (markerPtr->clipped) {
+ return; /* Bitmap is offscreen. Don't generate
+ * rotated or scaled bitmaps. */
+ }
+
+ /*
+ * Scale the bitmap if necessary. It's a little tricky because we only
+ * want to scale what's visible on the screen, not the entire bitmap.
+ */
+ if ((bmPtr->angle != 0.0f) || (destWidth != srcWidth) ||
+ (destHeight != srcHeight)) {
+ int regionX, regionY, regionWidth, regionHeight;
+ double left, right, top, bottom;
+
+ /* Ignore parts of the bitmap outside of the plot area. */
+ left = MAX(graphPtr->left, extents.left);
+ right = MIN(graphPtr->right, extents.right);
+ top = MAX(graphPtr->top, extents.top);
+ bottom = MIN(graphPtr->bottom, extents.bottom);
+
+ /* Determine the portion of the scaled bitmap to display. */
+ regionX = regionY = 0;
+ if (graphPtr->left > extents.left) {
+ regionX = (int)(graphPtr->left - extents.left);
+ }
+ if (graphPtr->top > extents.top) {
+ regionY = (int)(graphPtr->top - extents.top);
+ }
+ regionWidth = (int)(right - left) + 1;
+ regionHeight = (int)(bottom - top) + 1;
+
+ anchorPt.x = left;
+ anchorPt.y = top;
+ bmPtr->destBitmap = Blt_ScaleRotateBitmapArea(graphPtr->tkwin,
+ bmPtr->srcBitmap, srcWidth, srcHeight, regionX, regionY,
+ regionWidth, regionHeight, destWidth, destHeight, bmPtr->angle);
+ bmPtr->destWidth = regionWidth;
+ bmPtr->destHeight = regionHeight;
+ } else {
+ bmPtr->destWidth = srcWidth;
+ bmPtr->destHeight = srcHeight;
+ bmPtr->destBitmap = None;
+ }
+ bmPtr->anchorPt = anchorPt;
+ {
+ double xScale, yScale;
+ double tx, ty;
+ double rotWidth, rotHeight;
+ Point2d polygon[5];
+ int n;
+
+ /*
+ * Compute a polygon to represent the background area of the bitmap.
+ * This is needed for backgrounds of arbitrarily rotated bitmaps. We
+ * also use it to print a background in PostScript.
+ */
+ Blt_GetBoundingBox(srcWidth, srcHeight, bmPtr->angle, &rotWidth,
+ &rotHeight, polygon);
+ xScale = (double)destWidth / rotWidth;
+ yScale = (double)destHeight / rotHeight;
+
+ /*
+ * Adjust each point of the polygon. Both scale it to the new size and
+ * translate it to the actual screen position of the bitmap.
+ */
+ tx = extents.left + destWidth * 0.5;
+ ty = extents.top + destHeight * 0.5;
+ for (i = 0; i < 4; i++) {
+ polygon[i].x = (polygon[i].x * xScale) + tx;
+ polygon[i].y = (polygon[i].y * yScale) + ty;
+ }
+ Blt_GraphExtents(graphPtr, &extents);
+ n = Blt_PolyRectClip(&extents, polygon, 4, bmPtr->outline);
+ assert(n <= MAX_OUTLINE_POINTS);
+ if (n < 3) {
+ memcpy(&bmPtr->outline, polygon, sizeof(Point2d) * 4);
+ bmPtr->nOutlinePts = 4;
+ } else {
+ bmPtr->nOutlinePts = n;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PointInBitmapProc --
+ *
+ * Indicates if the given point is over the bitmap marker. The area of
+ * the bitmap is the rectangle.
+ *
+ * Results:
+ * Returns 1 is the point is over the bitmap marker, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+PointInBitmapProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+
+ if (bmPtr->srcBitmap == None) {
+ return 0;
+ }
+ if (bmPtr->angle != 0.0f) {
+ Point2d points[MAX_OUTLINE_POINTS];
+ int i;
+
+ /*
+ * Generate the bounding polygon (isolateral) for the bitmap and see
+ * if the point is inside of it.
+ */
+ for (i = 0; i < bmPtr->nOutlinePts; i++) {
+ points[i].x = bmPtr->outline[i].x + bmPtr->anchorPt.x;
+ points[i].y = bmPtr->outline[i].y + bmPtr->anchorPt.y;
+ }
+ return Blt_PointInPolygon(samplePtr, points, bmPtr->nOutlinePts);
+ }
+ return ((samplePtr->x >= bmPtr->anchorPt.x) &&
+ (samplePtr->x < (bmPtr->anchorPt.x + bmPtr->destWidth)) &&
+ (samplePtr->y >= bmPtr->anchorPt.y) &&
+ (samplePtr->y < (bmPtr->anchorPt.y + bmPtr->destHeight)));
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RegionInBitmapProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RegionInBitmapProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+
+ if (markerPtr->nWorldPts < 1) {
+ return FALSE;
+ }
+ if (bmPtr->angle != 0.0f) {
+ Point2d points[MAX_OUTLINE_POINTS];
+ int i;
+
+ /*
+ * Generate the bounding polygon (isolateral) for the bitmap and see
+ * if the point is inside of it.
+ */
+ for (i = 0; i < bmPtr->nOutlinePts; i++) {
+ points[i].x = bmPtr->outline[i].x + bmPtr->anchorPt.x;
+ points[i].y = bmPtr->outline[i].y + bmPtr->anchorPt.y;
+ }
+ return Blt_RegionInPolygon(extsPtr, points, bmPtr->nOutlinePts,
+ enclosed);
+ }
+ if (enclosed) {
+ return ((bmPtr->anchorPt.x >= extsPtr->left) &&
+ (bmPtr->anchorPt.y >= extsPtr->top) &&
+ ((bmPtr->anchorPt.x + bmPtr->destWidth) <= extsPtr->right) &&
+ ((bmPtr->anchorPt.y + bmPtr->destHeight) <= extsPtr->bottom));
+ }
+ return !((bmPtr->anchorPt.x >= extsPtr->right) ||
+ (bmPtr->anchorPt.y >= extsPtr->bottom) ||
+ ((bmPtr->anchorPt.x + bmPtr->destWidth) <= extsPtr->left) ||
+ ((bmPtr->anchorPt.y + bmPtr->destHeight) <= extsPtr->top));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawBitmapProc --
+ *
+ * Draws the bitmap marker that have a transparent of filled background.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * GC stipple origins are changed to current window coordinates.
+ * Commands are output to X to draw the marker in its current mode.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawBitmapProc(Marker *markerPtr, Drawable drawable)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ double rangle;
+ Pixmap bitmap;
+
+ bitmap = GETBITMAP(bmPtr);
+ if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
+ return;
+ }
+ rangle = fmod(bmPtr->angle, 90.0);
+ if ((bmPtr->fillColor == NULL) || (rangle != 0.0)) {
+
+ /*
+ * If the bitmap is rotated and a filled background is required, then
+ * a filled polygon is drawn before the bitmap.
+ */
+ if (bmPtr->fillColor != NULL) {
+ int i;
+ XPoint polygon[MAX_OUTLINE_POINTS];
+
+ for (i = 0; i < bmPtr->nOutlinePts; i++) {
+ polygon[i].x = (short int)bmPtr->outline[i].x;
+ polygon[i].y = (short int)bmPtr->outline[i].y;
+ }
+ XFillPolygon(graphPtr->display, drawable, bmPtr->fillGC,
+ polygon, bmPtr->nOutlinePts, Convex, CoordModeOrigin);
+ }
+ XSetClipMask(graphPtr->display, bmPtr->gc, bitmap);
+ XSetClipOrigin(graphPtr->display, bmPtr->gc, (int)bmPtr->anchorPt.x,
+ (int)bmPtr->anchorPt.y);
+ } else {
+ XSetClipMask(graphPtr->display, bmPtr->gc, None);
+ XSetClipOrigin(graphPtr->display, bmPtr->gc, 0, 0);
+ }
+ XCopyPlane(graphPtr->display, bitmap, drawable, bmPtr->gc, 0, 0,
+ bmPtr->destWidth, bmPtr->destHeight, (int)bmPtr->anchorPt.x,
+ (int)bmPtr->anchorPt.y, 1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BitmapToPostscriptProc --
+ *
+ * Generates PostScript to print a bitmap marker.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+BitmapToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ Pixmap bitmap;
+
+ bitmap = GETBITMAP(bmPtr);
+ if ((bitmap == None) || (bmPtr->destWidth < 1) || (bmPtr->destHeight < 1)) {
+ return; /* No bitmap to display. */
+ }
+ if (bmPtr->fillColor != NULL) {
+ Blt_Ps_XSetBackground(ps, bmPtr->fillColor);
+ Blt_Ps_XFillPolygon(ps, bmPtr->outline, 4);
+ }
+ Blt_Ps_XSetForeground(ps, bmPtr->outlineColor);
+
+ Blt_Ps_Format(ps,
+ " gsave\n %g %g translate\n %d %d scale\n",
+ bmPtr->anchorPt.x, bmPtr->anchorPt.y + bmPtr->destHeight,
+ bmPtr->destWidth, -bmPtr->destHeight);
+ Blt_Ps_Format(ps, " %d %d true [%d 0 0 %d 0 %d] {",
+ bmPtr->destWidth, bmPtr->destHeight, bmPtr->destWidth,
+ -bmPtr->destHeight, bmPtr->destHeight);
+ Blt_Ps_XSetBitmapData(ps, graphPtr->display, bitmap,
+ bmPtr->destWidth, bmPtr->destHeight);
+ Blt_Ps_VarAppend(ps,
+ " } imagemask\n",
+ "grestore\n", (char *)NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeBitmapProc --
+ *
+ * Releases the memory and attributes of the bitmap marker.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Bitmap attributes (GCs, colors, bitmap, etc) get destroyed. Memory is
+ * released, X resources are freed, and the graph is redrawn.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeBitmapProc(Marker *markerPtr)
+{
+ BitmapMarker *bmPtr = (BitmapMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ if (bmPtr->gc != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->gc);
+ }
+ if (bmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, bmPtr->fillGC);
+ }
+ if (bmPtr->destBitmap != None) {
+ Tk_FreePixmap(graphPtr->display, bmPtr->destBitmap);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateBitmapProc --
+ *
+ * Allocate memory and initialize methods for the new bitmap marker.
+ *
+ * Results:
+ * The pointer to the newly allocated marker structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the bitmap marker structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Marker *
+CreateBitmapProc(void)
+{
+ BitmapMarker *bmPtr;
+
+ bmPtr = calloc(1, sizeof(BitmapMarker));
+ bmPtr->classPtr = &bitmapMarkerClass;
+ return (Marker *)bmPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureTextProc --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a text marker.
+ *
+ * Results:
+ * A standard TCL result. If TCL_ERROR is returned, then interp->result
+ * contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for markerPtr; old resources get freed, if there were any. The
+ * marker is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureTextProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+
+ tmPtr->style.angle = (float)fmod(tmPtr->style.angle, 360.0);
+ if (tmPtr->style.angle < 0.0f) {
+ tmPtr->style.angle += 360.0f;
+ }
+ newGC = NULL;
+ if (tmPtr->fillColor != NULL) {
+ gcMask = GCForeground;
+ gcValues.foreground = tmPtr->fillColor->pixel;
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ }
+ if (tmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, tmPtr->fillGC);
+ }
+ tmPtr->fillGC = newGC;
+
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapTextProc --
+ *
+ * Calculate the layout position for a text marker. Positional information
+ * is saved in the marker. If the text is rotated, a bitmap containing the
+ * text is created.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * If no background color has been specified, the GC stipple origins are
+ * changed to current window coordinates. For both rotated and
+ * non-rotated text, if any old bitmap is leftover, it is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapTextProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+ Region2d extents;
+ Point2d anchorPt;
+ int i;
+ unsigned int w, h;
+ double rw, rh;
+
+ tmPtr->width = tmPtr->height = 0;
+ if (tmPtr->string == NULL) {
+ return;
+ }
+ Blt_Ts_GetExtents(&tmPtr->style, tmPtr->string, &w, &h);
+ Blt_GetBoundingBox(w, h, tmPtr->style.angle, &rw, &rh, tmPtr->outline);
+ tmPtr->width = ROUND(rw);
+ tmPtr->height = ROUND(rh);
+ for (i = 0; i < 4; i++) {
+ tmPtr->outline[i].x += ROUND(rw * 0.5);
+ tmPtr->outline[i].y += ROUND(rh * 0.5);
+ }
+ tmPtr->outline[4].x = tmPtr->outline[0].x;
+ tmPtr->outline[4].y = tmPtr->outline[0].y;
+ anchorPt = MapPoint(markerPtr->worldPts, &markerPtr->axes);
+ anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, (double)(tmPtr->width),
+ (double)(tmPtr->height), tmPtr->anchor);
+ anchorPt.x += markerPtr->xOffset;
+ anchorPt.y += markerPtr->yOffset;
+ /*
+ * Determine the bounding box of the text and test to see if it is at
+ * least partially contained within the plotting area.
+ */
+ extents.left = anchorPt.x;
+ extents.top = anchorPt.y;
+ extents.right = anchorPt.x + tmPtr->width - 1;
+ extents.bottom = anchorPt.y + tmPtr->height - 1;
+ markerPtr->clipped = BoxesDontOverlap(graphPtr, &extents);
+ tmPtr->anchorPt = anchorPt;
+
+}
+
+static int
+PointInTextProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+
+ if (tmPtr->string == NULL) {
+ return 0;
+ }
+ if (tmPtr->style.angle != 0.0f) {
+ Point2d points[5];
+ int i;
+
+ /*
+ * Figure out the bounding polygon (isolateral) for the text and see
+ * if the point is inside of it.
+ */
+ for (i = 0; i < 5; i++) {
+ points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x;
+ points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y;
+ }
+ return Blt_PointInPolygon(samplePtr, points, 5);
+ }
+ return ((samplePtr->x >= tmPtr->anchorPt.x) &&
+ (samplePtr->x < (tmPtr->anchorPt.x + tmPtr->width)) &&
+ (samplePtr->y >= tmPtr->anchorPt.y) &&
+ (samplePtr->y < (tmPtr->anchorPt.y + tmPtr->height)));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RegionInTextProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RegionInTextProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
+{
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+
+ if (markerPtr->nWorldPts < 1) {
+ return FALSE;
+ }
+ if (tmPtr->style.angle != 0.0f) {
+ Point2d points[5];
+ int i;
+
+ /*
+ * Generate the bounding polygon (isolateral) for the bitmap and see
+ * if the point is inside of it.
+ */
+ for (i = 0; i < 4; i++) {
+ points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x;
+ points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y;
+ }
+ return Blt_RegionInPolygon(extsPtr, points, 4, enclosed);
+ }
+ if (enclosed) {
+ return ((tmPtr->anchorPt.x >= extsPtr->left) &&
+ (tmPtr->anchorPt.y >= extsPtr->top) &&
+ ((tmPtr->anchorPt.x + tmPtr->width) <= extsPtr->right) &&
+ ((tmPtr->anchorPt.y + tmPtr->height) <= extsPtr->bottom));
+ }
+ return !((tmPtr->anchorPt.x >= extsPtr->right) ||
+ (tmPtr->anchorPt.y >= extsPtr->bottom) ||
+ ((tmPtr->anchorPt.x + tmPtr->width) <= extsPtr->left) ||
+ ((tmPtr->anchorPt.y + tmPtr->height) <= extsPtr->top));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawTextProc --
+ *
+ * Draws the text marker on the graph.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to draw the marker in its current mode.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawTextProc(Marker *markerPtr, Drawable drawable)
+{
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ if (tmPtr->string == NULL) {
+ return;
+ }
+ if (tmPtr->fillGC != NULL) {
+ XPoint points[4];
+ int i;
+
+ /*
+ * Simulate the rotated background of the bitmap by filling a bounding
+ * polygon with the background color.
+ */
+ for (i = 0; i < 4; i++) {
+ points[i].x = (short int)(tmPtr->outline[i].x + tmPtr->anchorPt.x);
+ points[i].y = (short int)(tmPtr->outline[i].y + tmPtr->anchorPt.y);
+ }
+ XFillPolygon(graphPtr->display, drawable, tmPtr->fillGC, points, 4,
+ Convex, CoordModeOrigin);
+ }
+ if (tmPtr->style.color != NULL) {
+ Blt_Ts_DrawText(graphPtr->tkwin, drawable, tmPtr->string, -1,
+ &tmPtr->style, (int)tmPtr->anchorPt.x, (int)tmPtr->anchorPt.y);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TextToPostscriptProc --
+ *
+ * Outputs PostScript commands to draw a text marker at a given x,y
+ * coordinate, rotation, anchor, and font.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript font and color settings are changed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+TextToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+
+ if (tmPtr->string == NULL) {
+ return;
+ }
+ if (tmPtr->fillGC != NULL) {
+ Point2d points[4];
+ int i;
+
+ /*
+ * Simulate the rotated background of the bitmap by filling a bounding
+ * polygon with the background color.
+ */
+ for (i = 0; i < 4; i++) {
+ points[i].x = tmPtr->outline[i].x + tmPtr->anchorPt.x;
+ points[i].y = tmPtr->outline[i].y + tmPtr->anchorPt.y;
+ }
+ Blt_Ps_XSetBackground(ps, tmPtr->fillColor);
+ Blt_Ps_XFillPolygon(ps, points, 4);
+ }
+ Blt_Ps_DrawText(ps, tmPtr->string, &tmPtr->style, tmPtr->anchorPt.x,
+ tmPtr->anchorPt.y);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeTextProc --
+ *
+ * Destroys the structure containing the attributes of the text marker.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Text attributes (GCs, colors, stipple, font, etc) get destroyed.
+ * Memory is released, X resources are freed, and the graph is redrawn.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeTextProc(Marker *markerPtr)
+{
+ TextMarker *tmPtr = (TextMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ Blt_Ts_FreeStyle(graphPtr->display, &tmPtr->style);
+}
+
+/*
+ *---------------------------------------------------------------------------
+
+ * CreateTextProc --
+ *
+ * Allocate memory and initialize methods for the new text marker.
+ *
+ * Results:
+ * The pointer to the newly allocated marker structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the text marker structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Marker *
+CreateTextProc(void)
+{
+ TextMarker *tmPtr;
+
+ tmPtr = calloc(1, sizeof(TextMarker));
+ tmPtr->classPtr = &textMarkerClass;
+ Blt_Ts_InitStyle(tmPtr->style);
+ tmPtr->style.anchor = TK_ANCHOR_NW;
+ tmPtr->style.padLeft = tmPtr->style.padRight = 4;
+ tmPtr->style.padTop = tmPtr->style.padBottom = 4;
+ return (Marker *)tmPtr;
+}
+
+static Tk_EventProc ChildEventProc;
+static Tk_GeomRequestProc ChildGeometryProc;
+static Tk_GeomLostSlaveProc ChildCustodyProc;
+static Tk_GeomMgr winMarkerMgrInfo =
+{
+ (char *)"graph", /* Name of geometry manager used by
+ * winfo */
+ ChildGeometryProc, /* Procedure to for new geometry
+ * requests. */
+ ChildCustodyProc, /* Procedure when window is taken
+ * away. */
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureWindowProc --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a window
+ * marker.
+ *
+ * Results:
+ * A standard TCL result. If TCL_ERROR is returned, then interp->result
+ * contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as window pathname, placement,
+ * etc. get set for markerPtr; old resources get freed, if there were
+ * any. The marker is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureWindowProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+ Tk_Window tkwin;
+
+ if (wmPtr->childName == NULL) {
+ return TCL_OK;
+ }
+ tkwin = Tk_NameToWindow(graphPtr->interp, wmPtr->childName,
+ graphPtr->tkwin);
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tk_Parent(tkwin) != graphPtr->tkwin) {
+ Tcl_AppendResult(graphPtr->interp, "\"", wmPtr->childName,
+ "\" is not a child of \"", Tk_PathName(graphPtr->tkwin), "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (tkwin != wmPtr->child) {
+ if (wmPtr->child != NULL) {
+ Tk_DeleteEventHandler(wmPtr->child, StructureNotifyMask,
+ ChildEventProc, wmPtr);
+ Tk_ManageGeometry(wmPtr->child, (Tk_GeomMgr *) 0, (ClientData)0);
+ Tk_UnmapWindow(wmPtr->child);
+ }
+ Tk_CreateEventHandler(tkwin, StructureNotifyMask, ChildEventProc,
+ wmPtr);
+ Tk_ManageGeometry(tkwin, &winMarkerMgrInfo, wmPtr);
+ }
+ wmPtr->child = tkwin;
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapWindowProc --
+ *
+ * Calculate the layout position for a window marker. Positional
+ * information is saved in the marker.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapWindowProc(Marker *markerPtr)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ Point2d anchorPt;
+ Region2d extents;
+ int width, height;
+
+ if (wmPtr->child == (Tk_Window)NULL) {
+ return;
+ }
+ anchorPt = MapPoint(markerPtr->worldPts, &markerPtr->axes);
+
+ width = Tk_ReqWidth(wmPtr->child);
+ height = Tk_ReqHeight(wmPtr->child);
+ if (wmPtr->reqWidth > 0) {
+ width = wmPtr->reqWidth;
+ }
+ if (wmPtr->reqHeight > 0) {
+ height = wmPtr->reqHeight;
+ }
+ wmPtr->anchorPt = Blt_AnchorPoint(anchorPt.x, anchorPt.y, (double)width,
+ (double)height, wmPtr->anchor);
+ wmPtr->anchorPt.x += markerPtr->xOffset;
+ wmPtr->anchorPt.y += markerPtr->yOffset;
+ wmPtr->width = width;
+ wmPtr->height = height;
+
+ /*
+ * Determine the bounding box of the window and test to see if it is at
+ * least partially contained within the plotting area.
+ */
+ extents.left = wmPtr->anchorPt.x;
+ extents.top = wmPtr->anchorPt.y;
+ extents.right = wmPtr->anchorPt.x + wmPtr->width - 1;
+ extents.bottom = wmPtr->anchorPt.y + wmPtr->height - 1;
+ markerPtr->clipped = BoxesDontOverlap(graphPtr, &extents);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PointInWindowProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+PointInWindowProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+
+ return ((samplePtr->x >= wmPtr->anchorPt.x) &&
+ (samplePtr->x < (wmPtr->anchorPt.x + wmPtr->width)) &&
+ (samplePtr->y >= wmPtr->anchorPt.y) &&
+ (samplePtr->y < (wmPtr->anchorPt.y + wmPtr->height)));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RegionInWindowProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RegionInWindowProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+
+ if (markerPtr->nWorldPts < 1) {
+ return FALSE;
+ }
+ if (enclosed) {
+ return ((wmPtr->anchorPt.x >= extsPtr->left) &&
+ (wmPtr->anchorPt.y >= extsPtr->top) &&
+ ((wmPtr->anchorPt.x + wmPtr->width) <= extsPtr->right) &&
+ ((wmPtr->anchorPt.y + wmPtr->height) <= extsPtr->bottom));
+ }
+ return !((wmPtr->anchorPt.x >= extsPtr->right) ||
+ (wmPtr->anchorPt.y >= extsPtr->bottom) ||
+ ((wmPtr->anchorPt.x + wmPtr->width) <= extsPtr->left) ||
+ ((wmPtr->anchorPt.y + wmPtr->height) <= extsPtr->top));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawWindowProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+DrawWindowProc(Marker *markerPtr, Drawable drawable)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+
+ if (wmPtr->child == NULL) {
+ return;
+ }
+ if ((wmPtr->height != Tk_Height(wmPtr->child)) ||
+ (wmPtr->width != Tk_Width(wmPtr->child)) ||
+ ((int)wmPtr->anchorPt.x != Tk_X(wmPtr->child)) ||
+ ((int)wmPtr->anchorPt.y != Tk_Y(wmPtr->child))) {
+ Tk_MoveResizeWindow(wmPtr->child, (int)wmPtr->anchorPt.x,
+ (int)wmPtr->anchorPt.y, wmPtr->width, wmPtr->height);
+ }
+ if (!Tk_IsMapped(wmPtr->child)) {
+ Tk_MapWindow(wmPtr->child);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * WindowToPostscriptProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+WindowToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+
+ if (wmPtr->child == NULL) {
+ return;
+ }
+ if (Tk_IsMapped(wmPtr->child)) {
+ // Blt_Ps_XDrawWindow(ps, wmPtr->child, wmPtr->anchorPt.x, wmPtr->anchorPt.y);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeWindowProc --
+ *
+ * Destroys the structure containing the attributes of the window *
+ * marker.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Window is destroyed and removed from the screen.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeWindowProc(Marker *markerPtr)
+{
+ WindowMarker *wmPtr = (WindowMarker *)markerPtr;
+
+ if (wmPtr->child != NULL) {
+ Tk_DeleteEventHandler(wmPtr->child, StructureNotifyMask,
+ ChildEventProc, wmPtr);
+ Tk_ManageGeometry(wmPtr->child, (Tk_GeomMgr *) 0, (ClientData)0);
+ Tk_DestroyWindow(wmPtr->child);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateWindowProc --
+ *
+ * Allocate memory and initialize methods for the new window marker.
+ *
+ * Results:
+ * The pointer to the newly allocated marker structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the window marker structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Marker *
+CreateWindowProc(void)
+{
+ WindowMarker *wmPtr;
+
+ wmPtr = calloc(1, sizeof(WindowMarker));
+ wmPtr->classPtr = &windowMarkerClass;
+ return (Marker *)wmPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ChildEventProc --
+ *
+ * This procedure is invoked whenever StructureNotify events occur for a
+ * window that's managed as part of a graph window marker. This
+ * procedure's only purpose is to clean up when windows are deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The window is disassociated from the window item when it is
+ * deleted.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ChildEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ WindowMarker *wmPtr = clientData;
+
+ if (eventPtr->type == DestroyNotify) {
+ wmPtr->child = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ChildGeometryProc --
+ *
+ * This procedure is invoked whenever a window that's associated with a
+ * window item changes its requested dimensions.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The size and location on the window of the window may change,
+ * depending on the options specified for the window item.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+ChildGeometryProc(ClientData clientData, Tk_Window tkwin)
+{
+ WindowMarker *wmPtr = clientData;
+
+ if (wmPtr->reqWidth == 0) {
+ wmPtr->width = Tk_ReqWidth(tkwin);
+ }
+ if (wmPtr->reqHeight == 0) {
+ wmPtr->height = Tk_ReqHeight(tkwin);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ChildCustodyProc --
+ *
+ * This procedure is invoked when an embedded window has been stolen by
+ * another geometry manager. The information and memory associated with
+ * the widget is released.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Arranges for the graph to be redrawn without the embedded widget at
+ * the next idle point.
+ *
+ *---------------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+static void
+ChildCustodyProc(ClientData clientData, Tk_Window tkwin)
+{
+ Marker *markerPtr = clientData;
+ Graph *graphPtr;
+
+ graphPtr = markerPtr->obj.graphPtr;
+ markerPtr->flags |= DELETE_PENDING;
+ Tcl_EventuallyFree(markerPtr, FreeMarker);
+ /*
+ * Not really needed. We should get an Expose event when the child window
+ * is unmapped.
+ */
+ Blt_EventuallyRedrawGraph(graphPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapLineProc --
+ *
+ * Calculate the layout position for a line marker. Positional
+ * information is saved in the marker. The line positions are stored in
+ * an array of points (malloc'ed).
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapLineProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+ Point2d *srcPtr, *pend;
+ Segment2d *segments, *segPtr;
+ Point2d p, q;
+ Region2d extents;
+
+ lmPtr->nSegments = 0;
+ if (lmPtr->segments != NULL) {
+ free(lmPtr->segments);
+ }
+ if (markerPtr->nWorldPts < 2) {
+ return; /* Too few points */
+ }
+ Blt_GraphExtents(graphPtr, &extents);
+
+ /*
+ * Allow twice the number of world coordinates. The line will represented
+ * as series of line segments, not one continous polyline. This is
+ * because clipping against the plot area may chop the line into several
+ * disconnected segments.
+ */
+ segments = malloc(markerPtr->nWorldPts * sizeof(Segment2d));
+ srcPtr = markerPtr->worldPts;
+ p = MapPoint(srcPtr, &markerPtr->axes);
+ p.x += markerPtr->xOffset;
+ p.y += markerPtr->yOffset;
+
+ segPtr = segments;
+ for (srcPtr++, pend = markerPtr->worldPts + markerPtr->nWorldPts;
+ srcPtr < pend; srcPtr++) {
+ Point2d next;
+
+ next = MapPoint(srcPtr, &markerPtr->axes);
+ next.x += markerPtr->xOffset;
+ next.y += markerPtr->yOffset;
+ q = next;
+ if (Blt_LineRectClip(&extents, &p, &q)) {
+ segPtr->p = p;
+ segPtr->q = q;
+ segPtr++;
+ }
+ p = next;
+ }
+ lmPtr->nSegments = segPtr - segments;
+ lmPtr->segments = segments;
+ markerPtr->clipped = (lmPtr->nSegments == 0);
+}
+
+static int
+PointInLineProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+
+ return Blt_PointInSegments(samplePtr, lmPtr->segments, lmPtr->nSegments,
+ (double)markerPtr->obj.graphPtr->halo);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RegionInLineProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RegionInLineProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
+{
+ if (markerPtr->nWorldPts < 2) {
+ return FALSE;
+ }
+ if (enclosed) {
+ Point2d *pp, *pend;
+
+ for (pp = markerPtr->worldPts, pend = pp + markerPtr->nWorldPts;
+ pp < pend; pp++) {
+ Point2d p;
+
+ p = MapPoint(pp, &markerPtr->axes);
+ if ((p.x < extsPtr->left) && (p.x > extsPtr->right) &&
+ (p.y < extsPtr->top) && (p.y > extsPtr->bottom)) {
+ return FALSE;
+ }
+ }
+ return TRUE; /* All points inside bounding box. */
+ } else {
+ int count;
+ Point2d *pp, *pend;
+
+ count = 0;
+ for (pp = markerPtr->worldPts, pend = pp + (markerPtr->nWorldPts - 1);
+ pp < pend; pp++) {
+ Point2d p, q;
+
+ p = MapPoint(pp, &markerPtr->axes);
+ q = MapPoint(pp + 1, &markerPtr->axes);
+ if (Blt_LineRectClip(extsPtr, &p, &q)) {
+ count++;
+ }
+ }
+ return (count > 0); /* At least 1 segment passes through
+ * region. */
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawLineProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawLineProc(Marker *markerPtr, Drawable drawable)
+{
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+
+ if (lmPtr->nSegments > 0) {
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ Blt_Draw2DSegments(graphPtr->display, drawable, lmPtr->gc,
+ lmPtr->segments, lmPtr->nSegments);
+ if (lmPtr->xor) { /* Toggle the drawing state */
+ lmPtr->xorState = (lmPtr->xorState == 0);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureLineProc --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a line marker.
+ *
+ * Results:
+ * A standard TCL result. If TCL_ERROR is returned, then interp->result
+ * contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as line width, colors, dashes,
+ * etc. get set for markerPtr; old resources get freed, if there were
+ * any. The marker is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ConfigureLineProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+ Drawable drawable;
+
+ drawable = Tk_WindowId(graphPtr->tkwin);
+ gcMask = (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
+ if (lmPtr->outlineColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = lmPtr->outlineColor->pixel;
+ }
+ if (lmPtr->fillColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = lmPtr->fillColor->pixel;
+ }
+ gcValues.cap_style = lmPtr->capStyle;
+ gcValues.join_style = lmPtr->joinStyle;
+ gcValues.line_width = LineWidth(lmPtr->lineWidth);
+ gcValues.line_style = LineSolid;
+ if (LineIsDashed(lmPtr->dashes)) {
+ gcValues.line_style =
+ (gcMask & GCBackground) ? LineDoubleDash : LineOnOffDash;
+ }
+ if (lmPtr->xor) {
+ unsigned long pixel;
+ gcValues.function = GXxor;
+
+ gcMask |= GCFunction;
+ if (graphPtr->plotBg == NULL) {
+ pixel = WhitePixelOfScreen(Tk_Screen(graphPtr->tkwin));
+ } else {
+ pixel = Blt_BackgroundBorderColor(graphPtr->plotBg)->pixel;
+ }
+ if (gcMask & GCBackground) {
+ gcValues.background ^= pixel;
+ }
+ gcValues.foreground ^= pixel;
+ if (drawable != None) {
+ DrawLineProc(markerPtr, drawable);
+ }
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (lmPtr->gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, lmPtr->gc);
+ }
+ if (LineIsDashed(lmPtr->dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &lmPtr->dashes);
+ }
+ lmPtr->gc = newGC;
+ if (lmPtr->xor) {
+ if (drawable != None) {
+ MapLineProc(markerPtr);
+ DrawLineProc(markerPtr, drawable);
+ }
+ return TCL_OK;
+ }
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LineToPostscriptProc --
+ *
+ * Prints postscript commands to display the connect line. Dashed lines
+ * need to be handled specially, especially if a background color is
+ * designated.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * PostScript output commands are saved in the interpreter
+ * (infoPtr->interp) result field.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+LineToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+
+ if (lmPtr->nSegments > 0) {
+ Blt_Ps_XSetLineAttributes(ps, lmPtr->outlineColor,
+ lmPtr->lineWidth, &lmPtr->dashes, lmPtr->capStyle,
+ lmPtr->joinStyle);
+ if ((LineIsDashed(lmPtr->dashes)) && (lmPtr->fillColor != NULL)) {
+ Blt_Ps_Append(ps, "/DashesProc {\n gsave\n ");
+ Blt_Ps_XSetBackground(ps, lmPtr->fillColor);
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
+ Blt_Ps_VarAppend(ps,
+ "stroke\n",
+ " grestore\n",
+ "} def\n", (char *)NULL);
+ } else {
+ Blt_Ps_Append(ps, "/DashesProc {} def\n");
+ }
+ Blt_Ps_Draw2DSegments(ps, lmPtr->segments, lmPtr->nSegments);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeLineProc --
+ *
+ * Destroys the structure and attributes of a line marker.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Line attributes (GCs, colors, stipple, etc) get released. Memory is
+ * deallocated, X resources are freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeLineProc(Marker *markerPtr)
+{
+ LineMarker *lmPtr = (LineMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ if (lmPtr->gc != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, lmPtr->gc);
+ }
+ if (lmPtr->segments != NULL) {
+ free(lmPtr->segments);
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateLineProc --
+ *
+ * Allocate memory and initialize methods for a new line marker.
+ *
+ * Results:
+ * The pointer to the newly allocated marker structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the line marker structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Marker *
+CreateLineProc(void)
+{
+ LineMarker *lmPtr;
+
+ lmPtr = calloc(1, sizeof(LineMarker));
+ lmPtr->classPtr = &lineMarkerClass;
+ lmPtr->xor = FALSE;
+ lmPtr->capStyle = CapButt;
+ lmPtr->joinStyle = JoinMiter;
+ return (Marker *)lmPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapPolygonProc --
+ *
+ * Calculate the layout position for a polygon marker. Positional
+ * information is saved in the polygon in an array of points (malloc'ed).
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MapPolygonProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ Point2d *screenPts;
+ Region2d extents;
+ int nScreenPts;
+
+ if (pmPtr->outlinePts != NULL) {
+ free(pmPtr->outlinePts);
+ pmPtr->outlinePts = NULL;
+ pmPtr->nOutlinePts = 0;
+ }
+ if (pmPtr->fillPts != NULL) {
+ free(pmPtr->fillPts);
+ pmPtr->fillPts = NULL;
+ pmPtr->nFillPts = 0;
+ }
+ if (pmPtr->screenPts != NULL) {
+ free(pmPtr->screenPts);
+ pmPtr->screenPts = NULL;
+ }
+ if (markerPtr->nWorldPts < 3) {
+ return; /* Too few points */
+ }
+
+ /*
+ * Allocate and fill a temporary array to hold the screen coordinates of
+ * the polygon.
+ */
+ nScreenPts = markerPtr->nWorldPts + 1;
+ screenPts = malloc((nScreenPts + 1) * sizeof(Point2d));
+ {
+ Point2d *sp, *dp, *send;
+
+ dp = screenPts;
+ for (sp = markerPtr->worldPts, send = sp + markerPtr->nWorldPts;
+ sp < send; sp++) {
+ *dp = MapPoint(sp, &markerPtr->axes);
+ dp->x += markerPtr->xOffset;
+ dp->y += markerPtr->yOffset;
+ dp++;
+ }
+ *dp = screenPts[0];
+ }
+ Blt_GraphExtents(graphPtr, &extents);
+ markerPtr->clipped = TRUE;
+ if (pmPtr->fill.fgColor != NULL) { /* Polygon fill required. */
+ Point2d *fillPts;
+ int n;
+
+ fillPts = malloc(sizeof(Point2d) * nScreenPts * 3);
+ n = Blt_PolyRectClip(&extents, screenPts, markerPtr->nWorldPts,fillPts);
+ if (n < 3) {
+ free(fillPts);
+ } else {
+ pmPtr->nFillPts = n;
+ pmPtr->fillPts = fillPts;
+ markerPtr->clipped = FALSE;
+ }
+ }
+ if ((pmPtr->outline.fgColor != NULL) && (pmPtr->lineWidth > 0)) {
+ Segment2d *outlinePts;
+ Segment2d *segPtr;
+ Point2d *sp, *send;
+
+ /*
+ * Generate line segments representing the polygon outline. The
+ * resulting outline may or may not be closed from viewport clipping.
+ */
+ outlinePts = malloc(nScreenPts * sizeof(Segment2d));
+ if (outlinePts == NULL) {
+ return; /* Can't allocate point array */
+ }
+ /*
+ * Note that this assumes that the point array contains an extra point
+ * that closes the polygon.
+ */
+ segPtr = outlinePts;
+ for (sp = screenPts, send = sp + (nScreenPts - 1); sp < send; sp++) {
+ segPtr->p = sp[0];
+ segPtr->q = sp[1];
+ if (Blt_LineRectClip(&extents, &segPtr->p, &segPtr->q)) {
+ segPtr++;
+ }
+ }
+ pmPtr->nOutlinePts = segPtr - outlinePts;
+ pmPtr->outlinePts = outlinePts;
+ if (pmPtr->nOutlinePts > 0) {
+ markerPtr->clipped = FALSE;
+ }
+ }
+ pmPtr->screenPts = screenPts;
+}
+
+static int
+PointInPolygonProc(Marker *markerPtr, Point2d *samplePtr)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
+ return Blt_PointInPolygon(samplePtr, pmPtr->screenPts,
+ markerPtr->nWorldPts + 1);
+ }
+ return FALSE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RegionInPolygonProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+RegionInPolygonProc(Marker *markerPtr, Region2d *extsPtr, int enclosed)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if ((markerPtr->nWorldPts >= 3) && (pmPtr->screenPts != NULL)) {
+ return Blt_RegionInPolygon(extsPtr, pmPtr->screenPts,
+ markerPtr->nWorldPts, enclosed);
+ }
+ return FALSE;
+}
+
+static void
+DrawPolygonProc(Marker *markerPtr, Drawable drawable)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ /* Draw polygon fill region */
+ if ((pmPtr->nFillPts > 0) && (pmPtr->fill.fgColor != NULL)) {
+ XPoint *dp, *points;
+ Point2d *sp, *send;
+
+ points = malloc(pmPtr->nFillPts * sizeof(XPoint));
+ if (points == NULL) {
+ return;
+ }
+ dp = points;
+ for (sp = pmPtr->fillPts, send = sp + pmPtr->nFillPts; sp < send;
+ sp++) {
+ dp->x = (short int)sp->x;
+ dp->y = (short int)sp->y;
+ dp++;
+ }
+
+ XFillPolygon(graphPtr->display, drawable, pmPtr->fillGC, points,
+ pmPtr->nFillPts, Complex, CoordModeOrigin);
+ free(points);
+ }
+ /* and then the outline */
+ if ((pmPtr->nOutlinePts > 0) && (pmPtr->lineWidth > 0) &&
+ (pmPtr->outline.fgColor != NULL)) {
+ Blt_Draw2DSegments(graphPtr->display, drawable, pmPtr->outlineGC,
+ pmPtr->outlinePts, pmPtr->nOutlinePts);
+ }
+}
+
+
+static void
+PolygonToPostscriptProc(Marker *markerPtr, Blt_Ps ps)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+
+ if (pmPtr->fill.fgColor != NULL) {
+
+ /*
+ * Options: fg bg
+ * Draw outline only.
+ * x Draw solid or stipple.
+ * x x Draw solid or stipple.
+ */
+
+ /* Create a path to use for both the polygon and its outline. */
+ Blt_Ps_Polyline(ps, pmPtr->fillPts, pmPtr->nFillPts);
+
+ /* If the background fill color was specified, draw the polygon in a
+ * solid fashion with that color. */
+ if (pmPtr->fill.bgColor != NULL) {
+ /* Draw the solid background as the background layer of the opaque
+ * stipple */
+ Blt_Ps_XSetBackground(ps, pmPtr->fill.bgColor);
+ /* Retain the path. We'll need it for the foreground layer. */
+ Blt_Ps_Append(ps, "gsave fill grestore\n");
+ }
+ Blt_Ps_XSetForeground(ps, pmPtr->fill.fgColor);
+ if (pmPtr->stipple != None) {
+ /* Draw the stipple in the foreground color. */
+ Blt_Ps_XSetStipple(ps, graphPtr->display, pmPtr->stipple);
+ } else {
+ Blt_Ps_Append(ps, "fill\n");
+ }
+ }
+
+ /* Draw the outline in the foreground color. */
+ if ((pmPtr->lineWidth > 0) && (pmPtr->outline.fgColor != NULL)) {
+
+ /* Set up the line attributes. */
+ Blt_Ps_XSetLineAttributes(ps, pmPtr->outline.fgColor,
+ pmPtr->lineWidth, &pmPtr->dashes, pmPtr->capStyle,
+ pmPtr->joinStyle);
+
+ /*
+ * Define on-the-fly a PostScript macro "DashesProc" that will be
+ * executed for each call to the Polygon drawing routine. If the line
+ * isn't dashed, simply make this an empty definition.
+ */
+ if ((pmPtr->outline.bgColor != NULL) && (LineIsDashed(pmPtr->dashes))) {
+ Blt_Ps_Append(ps, "/DashesProc {\ngsave\n ");
+ Blt_Ps_XSetBackground(ps, pmPtr->outline.bgColor);
+ Blt_Ps_Append(ps, " ");
+ Blt_Ps_XSetDashes(ps, (Blt_Dashes *)NULL);
+ Blt_Ps_Append(ps, "stroke\n grestore\n} def\n");
+ } else {
+ Blt_Ps_Append(ps, "/DashesProc {} def\n");
+ }
+ Blt_Ps_Draw2DSegments(ps, pmPtr->outlinePts, pmPtr->nOutlinePts);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigurePolygonProc --
+ *
+ * This procedure is called to process an objv/objc list, plus the Tk
+ * option database, in order to configure (or reconfigure) a polygon
+ * marker.
+ *
+ * Results:
+ * A standard TCL result. If TCL_ERROR is returned, then interp->result
+ * contains an error message.
+ *
+ * Side effects:
+ * Configuration information, such as polygon color, dashes, fillstyle,
+ * etc. get set for markerPtr; old resources get freed, if there were
+ * any. The marker is eventually redisplayed.
+ *
+ * --------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ConfigurePolygonProc(Marker *markerPtr)
+{
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+ Drawable drawable;
+
+ drawable = Tk_WindowId(graphPtr->tkwin);
+ gcMask = (GCLineWidth | GCLineStyle);
+ if (pmPtr->outline.fgColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = pmPtr->outline.fgColor->pixel;
+ }
+ if (pmPtr->outline.bgColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = pmPtr->outline.bgColor->pixel;
+ }
+ gcMask |= (GCCapStyle | GCJoinStyle);
+ gcValues.cap_style = pmPtr->capStyle;
+ gcValues.join_style = pmPtr->joinStyle;
+ gcValues.line_style = LineSolid;
+ gcValues.dash_offset = 0;
+ gcValues.line_width = LineWidth(pmPtr->lineWidth);
+ if (LineIsDashed(pmPtr->dashes)) {
+ gcValues.line_style = (pmPtr->outline.bgColor == NULL)
+ ? LineOnOffDash : LineDoubleDash;
+ }
+ if (pmPtr->xor) {
+ unsigned long pixel;
+ gcValues.function = GXxor;
+
+ gcMask |= GCFunction;
+ if (graphPtr->plotBg == NULL) {
+ /* The graph's color option may not have been set yet */
+ pixel = WhitePixelOfScreen(Tk_Screen(graphPtr->tkwin));
+ } else {
+ pixel = Blt_BackgroundBorderColor(graphPtr->plotBg)->pixel;
+ }
+ if (gcMask & GCBackground) {
+ gcValues.background ^= pixel;
+ }
+ gcValues.foreground ^= pixel;
+ if (drawable != None) {
+ DrawPolygonProc(markerPtr, drawable);
+ }
+ }
+ newGC = Blt_GetPrivateGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (LineIsDashed(pmPtr->dashes)) {
+ Blt_SetDashes(graphPtr->display, newGC, &pmPtr->dashes);
+ }
+ if (pmPtr->outlineGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
+ }
+ pmPtr->outlineGC = newGC;
+
+ gcMask = 0;
+ if (pmPtr->fill.fgColor != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = pmPtr->fill.fgColor->pixel;
+ }
+ if (pmPtr->fill.bgColor != NULL) {
+ gcMask |= GCBackground;
+ gcValues.background = pmPtr->fill.bgColor->pixel;
+ }
+ if (pmPtr->stipple != None) {
+ gcValues.stipple = pmPtr->stipple;
+ gcValues.fill_style = (pmPtr->fill.bgColor != NULL)
+ ? FillOpaqueStippled : FillStippled;
+ gcMask |= (GCStipple | GCFillStyle);
+ }
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (pmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
+ }
+ pmPtr->fillGC = newGC;
+
+ if ((gcMask == 0) && !(graphPtr->flags & RESET_AXES) && (pmPtr->xor)) {
+ if (drawable != None) {
+ MapPolygonProc(markerPtr);
+ DrawPolygonProc(markerPtr, drawable);
+ }
+ return TCL_OK;
+ }
+ markerPtr->flags |= MAP_ITEM;
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ graphPtr->flags |= RESET_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreePolygonProc --
+ *
+ * Release memory and resources allocated for the polygon element.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the polygon element is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreePolygonProc(Marker *markerPtr)
+{
+ PolygonMarker *pmPtr = (PolygonMarker *)markerPtr;
+ Graph *graphPtr = markerPtr->obj.graphPtr;
+
+ if (pmPtr->fillGC != NULL) {
+ Tk_FreeGC(graphPtr->display, pmPtr->fillGC);
+ }
+ if (pmPtr->outlineGC != NULL) {
+ Blt_FreePrivateGC(graphPtr->display, pmPtr->outlineGC);
+ }
+ if (pmPtr->fillPts != NULL) {
+ free(pmPtr->fillPts);
+ }
+ if (pmPtr->outlinePts != NULL) {
+ free(pmPtr->outlinePts);
+ }
+ if (pmPtr->screenPts != NULL) {
+ free(pmPtr->screenPts);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreatePolygonProc --
+ *
+ * Allocate memory and initialize methods for the new polygon marker.
+ *
+ * Results:
+ * The pointer to the newly allocated marker structure is returned.
+ *
+ * Side effects:
+ * Memory is allocated for the polygon marker structure.
+ *
+ * --------------------------------------------------------------------------
+ */
+static Marker *
+CreatePolygonProc(void)
+{
+ PolygonMarker *pmPtr;
+
+ pmPtr = calloc(1, sizeof(PolygonMarker));
+ pmPtr->classPtr = &polygonMarkerClass;
+ pmPtr->capStyle = CapButt;
+ pmPtr->joinStyle = JoinMiter;
+ return (Marker *)pmPtr;
+}
+
+static int
+GetMarkerFromObj(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ Marker **markerPtrPtr)
+{
+ Blt_HashEntry *hPtr;
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ hPtr = Blt_FindHashEntry(&graphPtr->markers.table, string);
+ if (hPtr != NULL) {
+ *markerPtrPtr = Blt_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find marker \"", string,
+ "\" in \"", Tk_PathName(graphPtr->tkwin), (char *)NULL);
+ }
+ return TCL_ERROR;
+}
+
+
+static int
+RenameMarker(Graph *graphPtr, Marker *markerPtr, const char *oldName,
+ const char *newName)
+{
+ int isNew;
+ Blt_HashEntry *hPtr;
+
+ /* Rename the marker only if no marker already exists by that name */
+ hPtr = Blt_CreateHashEntry(&graphPtr->markers.table, newName, &isNew);
+ if (!isNew) {
+ Tcl_AppendResult(graphPtr->interp, "can't rename marker: \"", newName,
+ "\" already exists", (char *)NULL);
+ return TCL_ERROR;
+ }
+ markerPtr->obj.name = Blt_Strdup(newName);
+ markerPtr->hashPtr = hPtr;
+ Blt_SetHashValue(hPtr, (char *)markerPtr);
+
+ /* Delete the old hash entry */
+ hPtr = Blt_FindHashEntry(&graphPtr->markers.table, oldName);
+ Blt_DeleteHashEntry(&graphPtr->markers.table, hPtr);
+ if (oldName != NULL) {
+ free((void*)oldName);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NamesOp --
+ *
+ * Returns a list of marker identifiers in interp->result;
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+NamesOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (objc == 3) {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(markerPtr->obj.name, -1));
+ }
+ } else {
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+ int i;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ for (i = 3; i < objc; i++) {
+ const char *pattern;
+
+ pattern = Tcl_GetString(objv[i]);
+ if (Tcl_StringMatch(markerPtr->obj.name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(markerPtr->obj.name, -1));
+ break;
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BindOp --
+ *
+ * .g element bind elemName sequence command
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+BindOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ Blt_HashEntry *hp;
+ Blt_HashSearch iter;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (hp = Blt_FirstHashEntry(&graphPtr->markers.tagTable, &iter);
+ hp != NULL; hp = Blt_NextHashEntry(&iter)) {
+ const char *tag;
+ Tcl_Obj *objPtr;
+
+ tag = Blt_GetHashKey(&graphPtr->markers.tagTable, hp);
+ objPtr = Tcl_NewStringObj(tag, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+ }
+ return Blt_ConfigureBindingsFromObj(interp, graphPtr->bindTable,
+ Blt_MakeMarkerTag(graphPtr, Tcl_GetString(objv[3])),
+ objc - 4, objv + 4);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+CgetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Marker *markerPtr;
+
+ if (GetMarkerFromObj(interp, graphPtr, objv[3], &markerPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Blt_ConfigureValueFromObj(interp, graphPtr->tkwin,
+ markerPtr->classPtr->configSpecs, (char *)markerPtr, objv[4], 0)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Marker *markerPtr;
+ Tcl_Obj *const *options;
+ const char *oldName;
+ const char *string;
+ int flags = BLT_CONFIG_OBJV_ONLY;
+ int nNames, nOpts;
+ int i;
+ int under;
+
+ markerPtr = NULL; /* Suppress compiler warning. */
+
+ /* Figure out where the option value pairs begin */
+ objc -= 3;
+ objv += 3;
+ for (i = 0; i < objc; i++) {
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ break;
+ }
+ if (GetMarkerFromObj(interp, graphPtr, objv[i], &markerPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ nNames = i; /* # of element names specified */
+ nOpts = objc - i; /* # of options specified */
+ options = objv + nNames; /* Start of options in objv */
+
+ for (i = 0; i < nNames; i++) {
+ GetMarkerFromObj(interp, graphPtr, objv[i], &markerPtr);
+ if (nOpts == 0) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ markerPtr->classPtr->configSpecs, (char *)markerPtr,
+ (Tcl_Obj *)NULL, flags);
+ } else if (nOpts == 1) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ markerPtr->classPtr->configSpecs, (char *)markerPtr,
+ options[0], flags);
+ }
+ /* Save the old marker name. */
+ oldName = markerPtr->obj.name;
+ under = markerPtr->drawUnder;
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin,
+ markerPtr->classPtr->configSpecs, nOpts, options,
+ (char *)markerPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (oldName != markerPtr->obj.name) {
+ if (RenameMarker(graphPtr, markerPtr, oldName, markerPtr->obj.name)
+ != TCL_OK) {
+ markerPtr->obj.name = oldName;
+ return TCL_ERROR;
+ }
+ }
+ if ((*markerPtr->classPtr->configProc) (markerPtr) != TCL_OK) {
+
+ return TCL_ERROR;
+ }
+ if (markerPtr->drawUnder != under) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateOp --
+ *
+ * This procedure creates and initializes a new marker.
+ *
+ * Results:
+ * The return value is a pointer to a structure describing the new
+ * element. If an error occurred, then the return value is NULL and an
+ * error message is left in interp->result.
+ *
+ * Side effects:
+ * Memory is allocated, etc.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+CreateOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Marker *markerPtr;
+ Blt_HashEntry *hPtr;
+ int isNew;
+ ClassId classId;
+ int i;
+ const char *name;
+ char ident[200];
+ const char *string;
+ char c;
+
+ string = Tcl_GetString(objv[3]);
+ c = string[0];
+ /* Create the new marker based upon the given type */
+ if ((c == 't') && (strcmp(string, "text") == 0)) {
+ classId = CID_MARKER_TEXT;
+ } else if ((c == 'l') && (strcmp(string, "line") == 0)) {
+ classId = CID_MARKER_LINE;
+ } else if ((c == 'p') && (strcmp(string, "polygon") == 0)) {
+ classId = CID_MARKER_POLYGON;
+ } else if ((c == 'i') && (strcmp(string, "image") == 0)) {
+ classId = CID_MARKER_IMAGE;
+ } else if ((c == 'b') && (strcmp(string, "bitmap") == 0)) {
+ classId = CID_MARKER_BITMAP;
+ } else if ((c == 'w') && (strcmp(string, "window") == 0)) {
+ classId = CID_MARKER_WINDOW;
+ } else {
+ Tcl_AppendResult(interp, "unknown marker type \"", string,
+ "\": should be \"text\", \"line\", \"polygon\", \"bitmap\", \"image\", or \
+\"window\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ /* Scan for "-name" option. We need it for the component name */
+ name = NULL;
+ for (i = 4; i < objc; i += 2) {
+ int length;
+
+ string = Tcl_GetStringFromObj(objv[i], &length);
+ if ((length > 1) && (strncmp(string, "-name", length) == 0)) {
+ name = Tcl_GetString(objv[i + 1]);
+ break;
+ }
+ }
+ /* If no name was given for the marker, make up one. */
+ if (name == NULL) {
+ sprintf_s(ident, 200, "marker%d", graphPtr->nextMarkerId++);
+ name = ident;
+ } else if (name[0] == '-') {
+ Tcl_AppendResult(interp, "name of marker \"", name,
+ "\" can't start with a '-'", (char *)NULL);
+ return TCL_ERROR;
+ }
+ markerPtr = CreateMarker(graphPtr, name, classId);
+ if (Blt_ConfigureComponentFromObj(interp, graphPtr->tkwin, name,
+ markerPtr->obj.className, markerPtr->classPtr->configSpecs,
+ objc - 4, objv + 4, (char *)markerPtr, 0) != TCL_OK) {
+ DestroyMarker(markerPtr);
+ return TCL_ERROR;
+ }
+ if ((*markerPtr->classPtr->configProc) (markerPtr) != TCL_OK) {
+ DestroyMarker(markerPtr);
+ return TCL_ERROR;
+ }
+ hPtr = Blt_CreateHashEntry(&graphPtr->markers.table, name, &isNew);
+ if (!isNew) {
+ Marker *oldPtr;
+ /*
+ * Marker by the same name already exists. Delete the old marker and
+ * it's list entry. But save the hash entry.
+ */
+ oldPtr = Blt_GetHashValue(hPtr);
+ oldPtr->hashPtr = NULL;
+ DestroyMarker(oldPtr);
+ }
+ Blt_SetHashValue(hPtr, markerPtr);
+ markerPtr->hashPtr = hPtr;
+ /* Unlike elements, new markers are drawn on top of old markers. */
+ markerPtr->link = Blt_Chain_Prepend(graphPtr->markers.displayList,markerPtr);
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), name, -1);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteOp --
+ *
+ * Deletes the marker given by markerId.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new display list.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+DeleteOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ Marker *markerPtr;
+
+ if (GetMarkerFromObj(NULL, graphPtr, objv[i], &markerPtr) == TCL_OK) {
+ markerPtr->flags |= DELETE_PENDING;
+ Tcl_EventuallyFree(markerPtr, FreeMarker);
+ }
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetOp --
+ *
+ * Find the legend entry from the given argument. The argument can be
+ * either a screen position "@x,y" or the name of an element.
+ *
+ * I don't know how useful it is to test with the name of an element.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new legend attributes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+GetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Marker *markerPtr;
+ const char *string;
+
+ string = Tcl_GetString(objv[3]);
+ if ((string[0] == 'c') && (strcmp(string, "current") == 0)) {
+ markerPtr = (Marker *)Blt_GetCurrentItem(graphPtr->bindTable);
+ if (markerPtr == NULL) {
+ return TCL_OK; /* Report only on markers. */
+
+ }
+ if ((markerPtr->obj.classId >= CID_MARKER_BITMAP) &&
+ (markerPtr->obj.classId <= CID_MARKER_WINDOW)) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ markerPtr->obj.name, -1);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RelinkOp --
+ *
+ * Reorders the marker (given by the first name) before/after the another
+ * marker (given by the second name) in the marker display list. If no
+ * second name is given, the marker is placed at the beginning/end of the
+ * list.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * Graph will be redrawn to reflect the new display list.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+RelinkOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_ChainLink link, place;
+ Marker *markerPtr;
+ const char *string;
+
+ /* Find the marker to be raised or lowered. */
+ if (GetMarkerFromObj(interp, graphPtr, objv[3], &markerPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Right now it's assumed that all markers are always in the display
+ list. */
+ link = markerPtr->link;
+ Blt_Chain_UnlinkLink(graphPtr->markers.displayList, markerPtr->link);
+
+ place = NULL;
+ if (objc == 5) {
+ if (GetMarkerFromObj(interp, graphPtr, objv[4], &markerPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ place = markerPtr->link;
+ }
+
+ /* Link the marker at its new position. */
+ string = Tcl_GetString(objv[2]);
+ if (string[0] == 'l') {
+ Blt_Chain_LinkAfter(graphPtr->markers.displayList, link, place);
+ } else {
+ Blt_Chain_LinkBefore(graphPtr->markers.displayList, link, place);
+ }
+ if (markerPtr->drawUnder) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindOp --
+ *
+ * Returns if marker by a given ID currently exists.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+FindOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_ChainLink link;
+ Region2d extents;
+ const char *string;
+ int enclosed;
+ int left, right, top, bottom;
+ int mode;
+
+#define FIND_ENCLOSED (1<<0)
+#define FIND_OVERLAPPING (1<<1)
+ string = Tcl_GetString(objv[3]);
+ if (strcmp(string, "enclosed") == 0) {
+ mode = FIND_ENCLOSED;
+ } else if (strcmp(string, "overlapping") == 0) {
+ mode = FIND_OVERLAPPING;
+ } else {
+ Tcl_AppendResult(interp, "bad search type \"", string,
+ ": should be \"enclosed\", or \"overlapping\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ if ((Tcl_GetIntFromObj(interp, objv[4], &left) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[5], &top) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[6], &right) != TCL_OK) ||
+ (Tcl_GetIntFromObj(interp, objv[7], &bottom) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (left < right) {
+ extents.left = (double)left;
+ extents.right = (double)right;
+ } else {
+ extents.left = (double)right;
+ extents.right = (double)left;
+ }
+ if (top < bottom) {
+ extents.top = (double)top;
+ extents.bottom = (double)bottom;
+ } else {
+ extents.top = (double)bottom;
+ extents.bottom = (double)top;
+ }
+ enclosed = (mode == FIND_ENCLOSED);
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ if (markerPtr->flags & (HIDE|DELETE_PENDING)) {
+ continue;
+ }
+ if ((markerPtr->elemName != NULL) && (IsElementHidden(markerPtr))) {
+ continue;
+ }
+ if ((*markerPtr->classPtr->regionProc)(markerPtr, &extents, enclosed)) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_GetObjResult(interp);
+ Tcl_SetStringObj(objPtr, markerPtr->obj.name, -1);
+ return TCL_OK;
+ }
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), "", -1);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ExistsOp --
+ *
+ * Returns if marker by a given ID currently exists.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ExistsOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&graphPtr->markers.table, Tcl_GetString(objv[3]));
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), (hPtr != NULL));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TypeOp --
+ *
+ * Returns a symbolic name for the type of the marker whose ID is given.
+ *
+ * Results:
+ * A standard TCL result. interp->result will contain the symbolic type
+ * of the marker.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TypeOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Marker *markerPtr;
+ const char *type;
+
+ if (GetMarkerFromObj(interp, graphPtr, objv[3], &markerPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (markerPtr->obj.classId) {
+ case CID_MARKER_BITMAP: type = "bitmap"; break;
+ case CID_MARKER_IMAGE: type = "image"; break;
+ case CID_MARKER_LINE: type = "line"; break;
+ case CID_MARKER_POLYGON: type = "polygon"; break;
+ case CID_MARKER_TEXT: type = "text"; break;
+ case CID_MARKER_WINDOW: type = "window"; break;
+ default: type = "???"; break;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), type, -1);
+ return TCL_OK;
+}
+
+/* Public routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_MarkerOp --
+ *
+ * This procedure is invoked to process the TCL command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Blt_OpSpec markerOps[] =
+{
+ {"bind", 1, BindOp, 3, 6, "marker sequence command",},
+ {"cget", 2, CgetOp, 5, 5, "marker option",},
+ {"configure", 2, ConfigureOp, 4, 0,"marker ?marker?... ?option value?...",},
+ {"create", 2, CreateOp, 4, 0, "type ?option value?...",},
+ {"delete", 1, DeleteOp, 3, 0, "?marker?...",},
+ {"exists", 1, ExistsOp, 4, 4, "marker",},
+ {"find", 1, FindOp, 8, 8, "enclosed|overlapping x1 y1 x2 y2",},
+ {"get", 1, GetOp, 4, 4, "name",},
+ {"lower", 1, RelinkOp, 4, 5, "marker ?afterMarker?",},
+ {"names", 1, NamesOp, 3, 0, "?pattern?...",},
+ {"raise", 1, RelinkOp, 4, 5, "marker ?beforeMarker?",},
+ {"type", 1, TypeOp, 4, 4, "marker",},
+};
+static int nMarkerOps = sizeof(markerOps) / sizeof(Blt_OpSpec);
+
+/*ARGSUSED*/
+int
+Blt_MarkerOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphMarkerProc *proc;
+ int result;
+
+ proc = Blt_GetOpFromObj(interp, nMarkerOps, markerOps, BLT_OP_ARG2,
+ objc, objv,0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ result = (*proc) (graphPtr, interp, objc, objv);
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_MarkersToPostScript --
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_MarkersToPostScript(Graph *graphPtr, Blt_Ps ps, int under)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ if ((markerPtr->classPtr->postscriptProc == NULL) ||
+ (markerPtr->nWorldPts == 0)) {
+ continue;
+ }
+ if (markerPtr->drawUnder != under) {
+ continue;
+ }
+ if (markerPtr->flags & (HIDE|DELETE_PENDING)) {
+ continue;
+ }
+ if ((markerPtr->elemName != NULL) && (IsElementHidden(markerPtr))) {
+ continue;
+ }
+ Blt_Ps_VarAppend(ps, "\n% Marker \"", markerPtr->obj.name,
+ "\" is a ", markerPtr->obj.className, ".\n", (char *)NULL);
+ (*markerPtr->classPtr->postscriptProc) (markerPtr, ps);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawMarkers --
+ *
+ * Calls the individual drawing routines (based on marker type) for each
+ * marker in the display list.
+ *
+ * A marker will not be drawn if
+ *
+ * 1) An element linked to the marker (indicated by elemName) is
+ * currently hidden.
+ *
+ * 2) No coordinates have been specified for the marker.
+ *
+ * 3) The marker is requesting to be drawn at a different level
+ * (above/below the elements) from the current mode.
+ *
+ * 4) The marker is configured as hidden (-hide option).
+ *
+ * 5) The marker isn't visible in the current viewport (i.e. clipped).
+ *
+ * Results:
+ * None
+ *
+ * Side Effects:
+ * Markers are drawn into the drawable (pixmap) which will eventually
+ * be displayed in the graph window.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawMarkers(Graph *graphPtr, Drawable drawable, int under)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_LastLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+
+ if ((markerPtr->nWorldPts == 0) ||
+ (markerPtr->drawUnder != under) ||
+ (markerPtr->clipped) ||
+ (markerPtr->flags & (DELETE_PENDING|HIDE))) {
+ continue;
+ }
+ if ((markerPtr->elemName != NULL) && (IsElementHidden(markerPtr))) {
+ continue;
+ }
+ (*markerPtr->classPtr->drawProc) (markerPtr, drawable);
+ }
+}
+
+void
+Blt_ConfigureMarkers(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ (*markerPtr->classPtr->configProc) (markerPtr);
+ }
+}
+
+void
+Blt_MapMarkers(Graph *graphPtr)
+{
+ Blt_ChainLink link;
+
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ if (markerPtr->nWorldPts == 0) {
+ continue;
+ }
+ if (markerPtr->flags & (HIDE|DELETE_PENDING)) {
+ continue;
+ }
+ if ((graphPtr->flags & MAP_ALL) || (markerPtr->flags & MAP_ITEM)) {
+ (*markerPtr->classPtr->mapProc) (markerPtr);
+ markerPtr->flags &= ~MAP_ITEM;
+ }
+ }
+}
+
+void
+Blt_DestroyMarkers(Graph *graphPtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->markers.table, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_GetHashValue(hPtr);
+ /*
+ * Dereferencing the pointer to the hash table prevents the hash table
+ * entry from being automatically deleted.
+ */
+ markerPtr->hashPtr = NULL;
+ DestroyMarker(markerPtr);
+ }
+ Blt_DeleteHashTable(&graphPtr->markers.table);
+ Blt_DeleteHashTable(&graphPtr->markers.tagTable);
+ Blt_Chain_Destroy(graphPtr->markers.displayList);
+}
+
+Marker *
+Blt_NearestMarker(
+ Graph *graphPtr,
+ int x, int y, /* Screen coordinates */
+ int under)
+{
+ Blt_ChainLink link;
+ Point2d point;
+
+ point.x = (double)x;
+ point.y = (double)y;
+ for (link = Blt_Chain_FirstLink(graphPtr->markers.displayList);
+ link != NULL; link = Blt_Chain_NextLink(link)) {
+ Marker *markerPtr;
+
+ markerPtr = Blt_Chain_GetValue(link);
+ if ((markerPtr->nWorldPts == 0) ||
+ (markerPtr->flags & (HIDE|DELETE_PENDING|MAP_ITEM))) {
+ continue; /* Don't consider markers that are
+ * pending to be mapped. Even if the
+ * marker has already been mapped, the
+ * coordinates could be invalid now.
+ * Better to pick no marker than the
+ * wrong marker. */
+
+ }
+ if ((markerPtr->elemName != NULL) && (IsElementHidden(markerPtr))) {
+ continue;
+ }
+ if ((markerPtr->drawUnder == under) &&
+ (markerPtr->state == STATE_NORMAL)) {
+ if ((*markerPtr->classPtr->pointProc) (markerPtr, &point)) {
+ return markerPtr;
+ }
+ }
+ }
+ return NULL;
+}
+
+ClientData
+Blt_MakeMarkerTag(Graph *graphPtr, const char *tagName)
+{
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ assert(tagName != NULL);
+ hPtr = Blt_CreateHashEntry(&graphPtr->markers.tagTable, tagName, &isNew);
+ return Blt_GetHashKey(&graphPtr->markers.tagTable, hPtr);
+}
+
+
diff --git a/tlt3.0/bltGrMisc.c b/tlt3.0/bltGrMisc.c
new file mode 100644
index 0000000..db4b178
--- /dev/null
+++ b/tlt3.0/bltGrMisc.c
@@ -0,0 +1,1005 @@
+
+
+/*
+ * bltGrMisc.c --
+ *
+ * This module implements miscellaneous routines for the BLT graph widget.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltGraph.h"
+
+#define ARROW_LEFT (0)
+#define ARROW_UP (1)
+#define ARROW_RIGHT (2)
+#define ARROW_DOWN (3)
+#define ARROW_OFFSET 4
+#define STD_ARROW_HEIGHT 3
+#define STD_ARROW_WIDTH ((2 * (ARROW_OFFSET - 1)) + 1)
+
+#define BLT_SCROLL_MODE_CANVAS (1<<0)
+#define BLT_SCROLL_MODE_LISTBOX (1<<1)
+#define BLT_SCROLL_MODE_HIERBOX (1<<2)
+
+static Blt_OptionParseProc ObjToPoint;
+static Blt_OptionPrintProc PointToObj;
+Blt_CustomOption bltPointOption =
+{
+ ObjToPoint, PointToObj, NULL, (ClientData)0
+};
+
+static Blt_OptionParseProc ObjToLimitsProc;
+static Blt_OptionPrintProc LimitsToObjProc;
+Blt_CustomOption bltLimitsOption =
+{
+ ObjToLimitsProc, LimitsToObjProc, NULL, (ClientData)0
+};
+
+
+/*
+ *---------------------------------------------------------------------------
+ * Custom option parse and print procedures
+ *---------------------------------------------------------------------------
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetXY --
+ *
+ * Converts a string in the form "@x,y" into an XPoint structure of the x
+ * and y coordinates.
+ *
+ * Results:
+ * A standard TCL result. If the string represents a valid position
+ * *pointPtr* will contain the converted x and y coordinates and TCL_OK
+ * is returned. Otherwise, TCL_ERROR is returned and interp->result will
+ * contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetXY(Tcl_Interp *interp, Tk_Window tkwin, const char *string,
+ int *xPtr, int *yPtr)
+{
+ char *comma;
+ int result;
+ int x, y;
+
+ if ((string == NULL) || (*string == '\0')) {
+ *xPtr = *yPtr = -SHRT_MAX;
+ return TCL_OK;
+ }
+ if (*string != '@') {
+ goto badFormat;
+ }
+ comma = strchr(string + 1, ',');
+ if (comma == NULL) {
+ goto badFormat;
+ }
+ *comma = '\0';
+ result = ((Tk_GetPixels(interp, tkwin, string + 1, &x) == TCL_OK) &&
+ (Tk_GetPixels(interp, tkwin, comma + 1, &y) == TCL_OK));
+ *comma = ',';
+ if (!result) {
+ Tcl_AppendResult(interp, ": can't parse position \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ *xPtr = x, *yPtr = y;
+ return TCL_OK;
+
+ badFormat:
+ Tcl_AppendResult(interp, "bad position \"", string,
+ "\": should be \"@x,y\"", (char *)NULL);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPoint --
+ *
+ * Convert the string representation of a legend XY position into window
+ * coordinates. The form of the string must be "@x,y" or none.
+ *
+ * Results:
+ * A standard TCL result. The symbol type is written into the
+ * widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPoint(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* New legend position string */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ XPoint *pointPtr = (XPoint *)(widgRec + offset);
+ int x, y;
+
+ if (Blt_GetXY(interp, tkwin, Tcl_GetString(objPtr), &x, &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pointPtr->x = x, pointPtr->y = y;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PointToObj --
+ *
+ * Convert the window coordinates into a string.
+ *
+ * Results:
+ * The string representing the coordinate position is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PointToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ XPoint *pointPtr = (XPoint *)(widgRec + offset);
+ Tcl_Obj *objPtr;
+
+ if ((pointPtr->x != -SHRT_MAX) && (pointPtr->y != -SHRT_MAX)) {
+ char string[200];
+
+ sprintf_s(string, 200, "@%d,%d", pointPtr->x, pointPtr->y);
+ objPtr = Tcl_NewStringObj(string, -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ return objPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToLimitsProc --
+ *
+ * Converts the list of elements into zero or more pixel values which
+ * determine the range of pixel values possible. An element can be in any
+ * form accepted by Tk_GetPixels. The list has a different meaning based
+ * upon the number of elements.
+ *
+ * # of elements:
+ *
+ * 0 - the limits are reset to the defaults.
+ * 1 - the minimum and maximum values are set to this
+ * value, freezing the range at a single value.
+ * 2 - first element is the minimum, the second is the
+ * maximum.
+ * 3 - first element is the minimum, the second is the
+ * maximum, and the third is the nominal value.
+ *
+ * Any element may be the empty string which indicates the default.
+ *
+ * Results:
+ * The return value is a standard TCL result. The min and max fields
+ * of the range are set.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToLimitsProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Widget of paneset */
+ Tcl_Obj *objPtr, /* New width list */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ Blt_Limits *limitsPtr = (Blt_Limits *)(widgRec + offset);
+
+ if (Blt_GetLimitsFromObj(interp, tkwin, objPtr, limitsPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LimitsToObjProc --
+ *
+ * Convert the limits of the pixel values allowed into a list.
+ *
+ * Results:
+ * The string representation of the limits is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+LimitsToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Row/column structure record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ Blt_Limits *limitsPtr = (Blt_Limits *)(widgRec + offset);
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (limitsPtr->flags & LIMITS_MIN_SET) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(limitsPtr->min));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (limitsPtr->flags & LIMITS_MAX_SET) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(limitsPtr->max));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (limitsPtr->flags & LIMITS_NOM_SET) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(limitsPtr->nom));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ return listObjPtr;
+}
+
+int
+Blt_PointInSegments(
+ Point2d *samplePtr,
+ Segment2d *segments,
+ int nSegments,
+ double halo)
+{
+ Segment2d *sp, *send;
+ double minDist;
+
+ minDist = DBL_MAX;
+ for (sp = segments, send = sp + nSegments; sp < send; sp++) {
+ double dist;
+ double left, right, top, bottom;
+ Point2d p, t;
+
+ t = Blt_GetProjection((int)samplePtr->x, (int)samplePtr->y,
+ &sp->p, &sp->q);
+ if (sp->p.x > sp->q.x) {
+ right = sp->p.x, left = sp->q.x;
+ } else {
+ right = sp->q.x, left = sp->p.x;
+ }
+ if (sp->p.y > sp->q.y) {
+ bottom = sp->p.y, top = sp->q.y;
+ } else {
+ bottom = sp->q.y, top = sp->p.y;
+ }
+ p.x = BOUND(t.x, left, right);
+ p.y = BOUND(t.y, top, bottom);
+ dist = hypot(p.x - samplePtr->x, p.y - samplePtr->y);
+ if (dist < minDist) {
+ minDist = dist;
+ }
+ }
+ return (minDist < halo);
+}
+
+int
+Blt_PointInPolygon(
+ Point2d *s, /* Sample point. */
+ Point2d *points, /* Points representing the polygon. */
+ int nPoints) /* # of points in above array. */
+{
+ Point2d *p, *q, *qend;
+ int count;
+
+ count = 0;
+ for (p = points, q = p + 1, qend = p + nPoints; q < qend; p++, q++) {
+ if (((p->y <= s->y) && (s->y < q->y)) ||
+ ((q->y <= s->y) && (s->y < p->y))) {
+ double b;
+
+ b = (q->x - p->x) * (s->y - p->y) / (q->y - p->y) + p->x;
+ if (s->x < b) {
+ count++; /* Count the number of intersections. */
+ }
+ }
+ }
+ return (count & 0x01);
+}
+
+int
+Blt_RegionInPolygon(
+ Region2d *regionPtr,
+ Point2d *points,
+ int nPoints,
+ int enclosed)
+{
+ Point2d *pp, *pend;
+
+ if (enclosed) {
+ /*
+ * All points of the polygon must be inside the rectangle.
+ */
+ for (pp = points, pend = pp + nPoints; pp < pend; pp++) {
+ if ((pp->x < regionPtr->left) || (pp->x > regionPtr->right) ||
+ (pp->y < regionPtr->top) || (pp->y > regionPtr->bottom)) {
+ return FALSE; /* One point is exterior. */
+ }
+ }
+ return TRUE;
+ } else {
+ Point2d r;
+ /*
+ * If any segment of the polygon clips the bounding region, the
+ * polygon overlaps the rectangle.
+ */
+ points[nPoints] = points[0];
+ for (pp = points, pend = pp + nPoints; pp < pend; pp++) {
+ Point2d p, q;
+
+ p = *pp;
+ q = *(pp + 1);
+ if (Blt_LineRectClip(regionPtr, &p, &q)) {
+ return TRUE;
+ }
+ }
+ /*
+ * Otherwise the polygon and rectangle are either disjoint or
+ * enclosed. Check if one corner of the rectangle is inside the
+ * polygon.
+ */
+ r.x = regionPtr->left;
+ r.y = regionPtr->top;
+ return Blt_PointInPolygon(&r, points, nPoints);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GraphExtents --
+ *
+ * Generates a bounding box representing the plotting area of the
+ * graph. This data structure is used to clip the points and line
+ * segments of the line element.
+ *
+ * The clip region is the plotting area plus such arbitrary extra space.
+ * The reason we clip with a bounding box larger than the plot area is so
+ * that symbols will be drawn even if their center point isn't in the
+ * plotting area.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The bounding box is filled with the dimensions of the plotting area.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_GraphExtents(Graph *graphPtr, Region2d *regionPtr)
+{
+ regionPtr->left = (double)(graphPtr->hOffset - graphPtr->xPad.side1);
+ regionPtr->top = (double)(graphPtr->vOffset - graphPtr->yPad.side1);
+ regionPtr->right = (double)(graphPtr->hOffset + graphPtr->hRange +
+ graphPtr->xPad.side2);
+ regionPtr->bottom = (double)(graphPtr->vOffset + graphPtr->vRange +
+ graphPtr->yPad.side2);
+}
+
+static int
+ClipTest (double ds, double dr, double *t1, double *t2)
+{
+ double t;
+
+ if (ds < 0.0) {
+ t = dr / ds;
+ if (t > *t2) {
+ return FALSE;
+ }
+ if (t > *t1) {
+ *t1 = t;
+ }
+ } else if (ds > 0.0) {
+ t = dr / ds;
+ if (t < *t1) {
+ return FALSE;
+ }
+ if (t < *t2) {
+ *t2 = t;
+ }
+ } else {
+ /* d = 0, so line is parallel to this clipping edge */
+ if (dr < 0.0) { /* Line is outside clipping edge */
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_LineRectClip --
+ *
+ * Clips the given line segment to a rectangular region. The coordinates
+ * of the clipped line segment are returned. The original coordinates
+ * are overwritten.
+ *
+ * Reference:
+ * Liang, Y-D., and B. Barsky, A new concept and method for
+ * Line Clipping, ACM, TOG,3(1), 1984, pp.1-22.
+ *
+ * Results:
+ * Returns if line segment is visible within the region. The coordinates
+ * of the original line segment are overwritten by the clipped
+ * coordinates.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_LineRectClip(
+ Region2d *regionPtr, /* Rectangular region to clip. */
+ Point2d *p, Point2d *q) /* (in/out) Coordinates of original and
+ * clipped line segment. */
+{
+ double t1, t2;
+ double dx, dy;
+
+ t1 = 0.0, t2 = 1.0;
+ dx = q->x - p->x;
+ if ((ClipTest (-dx, p->x - regionPtr->left, &t1, &t2)) &&
+ (ClipTest (dx, regionPtr->right - p->x, &t1, &t2))) {
+ dy = q->y - p->y;
+ if ((ClipTest (-dy, p->y - regionPtr->top, &t1, &t2)) &&
+ (ClipTest (dy, regionPtr->bottom - p->y, &t1, &t2))) {
+ if (t2 < 1.0) {
+ q->x = p->x + t2 * dx;
+ q->y = p->y + t2 * dy;
+ }
+ if (t1 > 0.0) {
+ p->x += t1 * dx;
+ p->y += t1 * dy;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_PolyRectClip --
+ *
+ * Clips the given polygon to a rectangular region. The resulting
+ * polygon is returned. Note that the resulting polyon may be complex,
+ * connected by zero width/height segments. The drawing routine (such as
+ * XFillPolygon) will not draw a connecting segment.
+ *
+ * Reference:
+ * Liang Y. D. and Brian A. Barsky, "Analysis and Algorithm for
+ * Polygon Clipping", Communications of ACM, Vol. 26,
+ * p.868-877, 1983
+ *
+ * Results:
+ * Returns the number of points in the clipped polygon. The points of the
+ * clipped polygon are stored in *outputPts*.
+ *
+ *---------------------------------------------------------------------------
+ */
+#define EPSILON FLT_EPSILON
+#define AddVertex(vx, vy) r->x=(vx), r->y=(vy), r++, count++
+#define LastVertex(vx, vy) r->x=(vx), r->y=(vy), count++
+
+int
+Blt_PolyRectClip(
+ Region2d *regionPtr, /* Rectangular region clipping the polygon. */
+ Point2d *points, /* Points of polygon to be clipped. */
+ int nPoints, /* # of points in polygon. */
+ Point2d *clipPts) /* (out) Points of clipped polygon. */
+{
+ Point2d *p; /* First vertex of input polygon edge. */
+ Point2d *pend;
+ Point2d *q; /* Last vertex of input polygon edge. */
+ Point2d *r;
+ int count;
+
+ r = clipPts;
+ count = 0; /* Counts # of vertices in output polygon. */
+
+ points[nPoints] = points[0];
+ for (p = points, q = p + 1, pend = p + nPoints; p < pend; p++, q++) {
+ double dx, dy;
+ double tin1, tin2, tinx, tiny;
+ double xin, yin, xout, yout;
+
+ dx = q->x - p->x; /* X-direction */
+ dy = q->y - p->y; /* Y-direction */
+
+ if (fabs(dx) < EPSILON) {
+ dx = (p->x > regionPtr->left) ? -EPSILON : EPSILON ;
+ }
+ if (fabs(dy) < EPSILON) {
+ dy = (p->y > regionPtr->top) ? -EPSILON : EPSILON ;
+ }
+
+ if (dx > 0.0) { /* Left */
+ xin = regionPtr->left;
+ xout = regionPtr->right + 1.0;
+ } else { /* Right */
+ xin = regionPtr->right + 1.0;
+ xout = regionPtr->left;
+ }
+ if (dy > 0.0) { /* Top */
+ yin = regionPtr->top;
+ yout = regionPtr->bottom + 1.0;
+ } else { /* Bottom */
+ yin = regionPtr->bottom + 1.0;
+ yout = regionPtr->top;
+ }
+
+ tinx = (xin - p->x) / dx;
+ tiny = (yin - p->y) / dy;
+
+ if (tinx < tiny) { /* Hits x first */
+ tin1 = tinx;
+ tin2 = tiny;
+ } else { /* Hits y first */
+ tin1 = tiny;
+ tin2 = tinx;
+ }
+
+ if (tin1 <= 1.0) {
+ if (tin1 > 0.0) {
+ AddVertex(xin, yin);
+ }
+ if (tin2 <= 1.0) {
+ double toutx, touty, tout1;
+
+ toutx = (xout - p->x) / dx;
+ touty = (yout - p->y) / dy;
+ tout1 = MIN(toutx, touty);
+
+ if ((tin2 > 0.0) || (tout1 > 0.0)) {
+ if (tin2 <= tout1) {
+ if (tin2 > 0.0) {
+ if (tinx > tiny) {
+ AddVertex(xin, p->y + tinx * dy);
+ } else {
+ AddVertex(p->x + tiny * dx, yin);
+ }
+ }
+ if (tout1 < 1.0) {
+ if (toutx < touty) {
+ AddVertex(xout, p->y + toutx * dy);
+ } else {
+ AddVertex(p->x + touty * dx, yout);
+ }
+ } else {
+ AddVertex(q->x, q->y);
+ }
+ } else {
+ if (tinx > tiny) {
+ AddVertex(xin, yout);
+ } else {
+ AddVertex(xout, yin);
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if (count > 0) {
+ LastVertex(clipPts[0].x, clipPts[0].y);
+ }
+ return count;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetProjection --
+ *
+ * Computes the projection of a point on a line. The line (given by two
+ * points), is assumed the be infinite.
+ *
+ * Compute the slope (angle) of the line and rotate it 90 degrees. Using
+ * the slope-intercept method (we know the second line from the sample
+ * test point and the computed slope), then find the intersection of both
+ * lines. This will be the projection of the sample point on the first
+ * line.
+ *
+ * Results:
+ * Returns the coordinates of the projection on the line.
+ *
+ *---------------------------------------------------------------------------
+ */
+Point2d
+Blt_GetProjection(
+ int x, int y, /* Screen coordinates of the sample point. */
+ Point2d *p, Point2d *q) /* Line segment to project point onto */
+{
+ double dx, dy;
+ Point2d t;
+
+ dx = p->x - q->x;
+ dy = p->y - q->y;
+
+ /* Test for horizontal and vertical lines */
+ if (fabs(dx) < DBL_EPSILON) {
+ t.x = p->x, t.y = (double)y;
+ } else if (fabs(dy) < DBL_EPSILON) {
+ t.x = (double)x, t.y = p->y;
+ } else {
+ double m1, m2; /* Slope of both lines */
+ double b1, b2; /* y-intercepts */
+ double midX, midY; /* Midpoint of line segment. */
+ double ax, ay, bx, by;
+
+ /* Compute the slope and intercept of PQ. */
+ m1 = (dy / dx);
+ b1 = p->y - (p->x * m1);
+
+ /*
+ * Compute the slope and intercept of a second line segment: one that
+ * intersects through sample X-Y coordinate with a slope perpendicular
+ * to original line.
+ */
+
+ /* Find midpoint of PQ. */
+ midX = (p->x + q->x) * 0.5;
+ midY = (p->y + q->y) * 0.5;
+
+ /* Rotate the line 90 degrees */
+ ax = midX - (0.5 * dy);
+ ay = midY - (0.5 * -dx);
+ bx = midX + (0.5 * dy);
+ by = midY + (0.5 * -dx);
+
+ m2 = (ay - by) / (ax - bx);
+ b2 = y - (x * m2);
+
+ /*
+ * Given the equations of two lines which contain the same point,
+ *
+ * y = m1 * x + b1
+ * y = m2 * x + b2
+ *
+ * solve for the intersection.
+ *
+ * x = (b2 - b1) / (m1 - m2)
+ * y = m1 * x + b1
+ *
+ */
+
+ t.x = (b2 - b1) / (m1 - m2);
+ t.y = m1 * t.x + b1;
+ }
+ return t;
+}
+
+#define SetColor(c,r,g,b) ((c)->red = (int)((r) * 65535.0), \
+ (c)->green = (int)((g) * 65535.0), \
+ (c)->blue = (int)((b) * 65535.0))
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_AdjustViewport --
+ *
+ * Adjusts the offsets of the viewport according to the scroll mode.
+ * This is to accommodate both "listbox" and "canvas" style scrolling.
+ *
+ * "canvas" The viewport scrolls within the range of world
+ * coordinates. This way the viewport always displays
+ * a full page of the world. If the world is smaller
+ * than the viewport, then (bizarrely) the world and
+ * viewport are inverted so that the world moves up
+ * and down within the viewport.
+ *
+ * "listbox" The viewport can scroll beyond the range of world
+ * coordinates. Every entry can be displayed at the
+ * top of the viewport. This also means that the
+ * scrollbar thumb weirdly shrinks as the last entry
+ * is scrolled upward.
+ *
+ * Results:
+ * The corrected offset is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_AdjustViewport(int offset, int worldSize, int windowSize, int scrollUnits,
+ int scrollMode)
+{
+ switch (scrollMode) {
+ case BLT_SCROLL_MODE_CANVAS:
+
+ /*
+ * Canvas-style scrolling allows the world to be scrolled within the
+ * window.
+ */
+ if (worldSize < windowSize) {
+ if ((worldSize - offset) > windowSize) {
+ offset = worldSize - windowSize;
+ }
+ if (offset > 0) {
+ offset = 0;
+ }
+ } else {
+ if ((offset + windowSize) > worldSize) {
+ offset = worldSize - windowSize;
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ }
+ break;
+
+ case BLT_SCROLL_MODE_LISTBOX:
+ if (offset < 0) {
+ offset = 0;
+ }
+ if (offset >= worldSize) {
+ offset = worldSize - scrollUnits;
+ }
+ break;
+
+ case BLT_SCROLL_MODE_HIERBOX:
+
+ /*
+ * Hierbox-style scrolling allows the world to be scrolled within the
+ * window.
+ */
+ if ((offset + windowSize) > worldSize) {
+ offset = worldSize - windowSize;
+ }
+ if (offset < 0) {
+ offset = 0;
+ }
+ break;
+ }
+ return offset;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_UpdateScrollbar --
+ *
+ * Invoke a TCL command to the scrollbar, defining the new position and
+ * length of the scroll. See the Tk documentation for further information
+ * on the scrollbar. It is assumed the scrollbar command prefix is
+ * valid.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Scrollbar is commanded to change position and/or size.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_UpdateScrollbar(
+ Tcl_Interp *interp,
+ Tcl_Obj *scrollCmdObjPtr, /* Scrollbar command prefix. May be
+ * several words */
+ int first, int last, int width)
+{
+ Tcl_Obj *cmdObjPtr;
+ double firstFract, lastFract;
+
+ firstFract = 0.0, lastFract = 1.0;
+ if (width > 0) {
+ firstFract = (double)first / (double)width;
+ lastFract = (double)last / (double)width;
+ }
+ cmdObjPtr = Tcl_DuplicateObj(scrollCmdObjPtr);
+ Tcl_ListObjAppendElement(interp, cmdObjPtr, Tcl_NewDoubleObj(firstFract));
+ Tcl_ListObjAppendElement(interp, cmdObjPtr, Tcl_NewDoubleObj(lastFract));
+ Tcl_IncrRefCount(cmdObjPtr);
+ if (Tcl_EvalObjEx(interp, cmdObjPtr, TCL_EVAL_GLOBAL) != TCL_OK) {
+ Tcl_BackgroundError(interp);
+ }
+ Tcl_DecrRefCount(cmdObjPtr);
+
+}
+
+/* -------------------------------------------------------------------------- */
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetPrivateGCFromDrawable --
+ *
+ * Like Tk_GetGC, but doesn't share the GC with any other widget. This
+ * is needed because the certain GC parameters (like dashes) can not be
+ * set via XCreateGC, therefore there is no way for Tk's hashing
+ * mechanism to recognize that two such GCs differ.
+ *
+ * Results:
+ * A new GC is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+GC
+Blt_GetPrivateGCFromDrawable(
+ Display *display,
+ Drawable drawable,
+ unsigned long gcMask,
+ XGCValues *valuePtr)
+{
+ GC newGC;
+
+ newGC = XCreateGC(display, drawable, gcMask, valuePtr);
+ return newGC;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetPrivateGC --
+ *
+ * Like Tk_GetGC, but doesn't share the GC with any other widget. This
+ * is needed because the certain GC parameters (like dashes) can not be
+ * set via XCreateGC, therefore there is no way for Tk's hashing
+ * mechanism to recognize that two such GCs differ.
+ *
+ * Results:
+ * A new GC is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+GC
+Blt_GetPrivateGC(
+ Tk_Window tkwin,
+ unsigned long gcMask,
+ XGCValues *valuePtr)
+{
+ GC gc;
+ Pixmap pixmap;
+ Drawable drawable;
+ Display *display;
+
+ pixmap = None;
+ drawable = Tk_WindowId(tkwin);
+ display = Tk_Display(tkwin);
+ if (drawable == None) {
+ Drawable root;
+ int depth;
+
+ root = Tk_RootWindow(tkwin);
+ depth = Tk_Depth(tkwin);
+
+ if (depth == DefaultDepth(display, Tk_ScreenNumber(tkwin))) {
+ drawable = root;
+ } else {
+ pixmap = Tk_GetPixmap(display, root, 1, 1, depth);
+ drawable = pixmap;
+ Blt_SetDrawableAttribs(display, drawable, 1, 1, depth,
+ Tk_Colormap(tkwin), Tk_Visual(tkwin));
+ }
+ }
+ gc = Blt_GetPrivateGCFromDrawable(display, drawable, gcMask, valuePtr);
+ if (pixmap != None) {
+ Tk_FreePixmap(display, pixmap);
+ }
+ return gc;
+}
+
+void
+Blt_FreePrivateGC(Display *display, GC gc)
+{
+ Tk_FreeXId(display, (XID) XGContextFromGC(gc));
+ XFreeGC(display, gc);
+}
+
+void
+Blt_SetDashes(Display *display, GC gc, Blt_Dashes *dashesPtr)
+{
+ XSetDashes(display, gc, dashesPtr->offset, (const char *)dashesPtr->values,
+ (int)strlen((char *)dashesPtr->values));
+}
+
+void
+Blt_ScreenDPI(Tk_Window tkwin, unsigned int *xPtr, unsigned int *yPtr)
+{
+ Screen *screen;
+
+#define MM_INCH 25.4
+ screen = Tk_Screen(tkwin);
+ *xPtr = (unsigned int)((WidthOfScreen(screen) * MM_INCH) /
+ WidthMMOfScreen(screen));
+ *yPtr = (unsigned int)((HeightOfScreen(screen) * MM_INCH) /
+ HeightMMOfScreen(screen));
+}
+
+void
+Blt_Draw2DSegments(
+ Display *display,
+ Drawable drawable,
+ GC gc,
+ Segment2d *segments,
+ int nSegments)
+{
+ XSegment *dp, *xsegments;
+ Segment2d *sp, *send;
+
+ xsegments = malloc(nSegments * sizeof(XSegment));
+ if (xsegments == NULL) {
+ return;
+ }
+ dp = xsegments;
+ for (sp = segments, send = sp + nSegments; sp < send; sp++) {
+ dp->x1 = (short int)sp->p.x;
+ dp->y1 = (short int)sp->p.y;
+ dp->x2 = (short int)sp->q.x;
+ dp->y2 = (short int)sp->q.y;
+ dp++;
+ }
+ XDrawSegments(display, drawable, gc, xsegments, nSegments);
+ free(xsegments);
+}
+
+long
+Blt_MaxRequestSize(Display *display, size_t elemSize)
+{
+ static long maxSizeBytes = 0L;
+
+ if (maxSizeBytes == 0L) {
+ long size;
+ size = XExtendedMaxRequestSize(display);
+ if (size == 0) {
+ size = XMaxRequestSize(display);
+ }
+ size -= (4 * elemSize);
+ /* maxSizeBytes = (size * 4); */
+ maxSizeBytes = size;
+ }
+ return (maxSizeBytes / elemSize);
+}
+
diff --git a/tlt3.0/bltGrPen.c b/tlt3.0/bltGrPen.c
new file mode 100644
index 0000000..79973a5
--- /dev/null
+++ b/tlt3.0/bltGrPen.c
@@ -0,0 +1,760 @@
+
+/*
+ * bltGrPen.c --
+ *
+ * This module implements pens for the BLT graph widget.
+ *
+ * Copyright 1996-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+
+typedef int (GraphPenProc)(Tcl_Interp *interp, Graph *graphPtr, int objc,
+ Tcl_Obj *const *objv);
+
+static Blt_OptionFreeProc FreeColor;
+static Blt_OptionParseProc ObjToColor;
+static Blt_OptionPrintProc ColorToObj;
+Blt_CustomOption bltColorOption = {
+ ObjToColor, ColorToObj, FreeColor, (ClientData)0
+};
+
+static Blt_OptionFreeProc FreePen;
+static Blt_OptionParseProc ObjToPen;
+static Blt_OptionPrintProc PenToObj;
+Blt_CustomOption bltBarPenOption = {
+ ObjToPen, PenToObj, FreePen, (ClientData)CID_ELEM_BAR
+};
+Blt_CustomOption bltLinePenOption = {
+ ObjToPen, PenToObj, FreePen, (ClientData)CID_ELEM_LINE
+};
+
+/*ARGSUSED*/
+static void
+FreeColor(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ XColor *colorPtr = *(XColor **)(widgRec + offset);
+
+ if ((colorPtr != NULL) && (colorPtr != COLOR_DEFAULT)) {
+ Tk_FreeColor(colorPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+
+ * ObjToColor --
+ *
+ * Convert the string representation of a color into a XColor pointer.
+ *
+ * Results:
+ * The return value is a standard TCL result. The color pointer is
+ * written into the widget record.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToColor(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing color */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ XColor **colorPtrPtr = (XColor **)(widgRec + offset);
+ XColor *colorPtr;
+ const char *string;
+ char c;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+
+ if ((c == '\0') && (flags & BLT_CONFIG_NULL_OK)) {
+ if ((*colorPtrPtr != NULL) && (*colorPtrPtr != COLOR_DEFAULT)) {
+ Tk_FreeColor(*colorPtrPtr);
+ }
+ *colorPtrPtr = NULL;
+ return TCL_OK;
+ }
+ if ((c == 'd') && (strncmp(string, "defcolor", length) == 0)) {
+ if ((*colorPtrPtr != NULL) && (*colorPtrPtr != COLOR_DEFAULT)) {
+ Tk_FreeColor(*colorPtrPtr);
+ }
+ *colorPtrPtr = COLOR_DEFAULT;
+ return TCL_OK;
+ }
+ colorPtr = Tk_AllocColorFromObj(interp, tkwin, objPtr);
+ if (colorPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if ((*colorPtrPtr != NULL) && (*colorPtrPtr != COLOR_DEFAULT)) {
+ Tk_FreeColor(*colorPtrPtr);
+ }
+ *colorPtrPtr = colorPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ColorToObj --
+ *
+ * Convert the color value into a string.
+ *
+ * Results:
+ * The string representing the symbol color is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+ColorToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ XColor *colorPtr = *(XColor **)(widgRec + offset);
+ Tcl_Obj *objPtr;
+
+ if (colorPtr == NULL) {
+ objPtr = Tcl_NewStringObj("", -1);
+ } else if (colorPtr == COLOR_DEFAULT) {
+ objPtr = Tcl_NewStringObj("defcolor", -1);
+ } else {
+ objPtr = Tcl_NewStringObj(Tk_NameOfColor(colorPtr), -1);
+ }
+ return objPtr;
+}
+
+/*ARGSUSED*/
+static void
+FreePen(
+ ClientData clientData, /* Not used. */
+ Display *display, /* Not used. */
+ char *widgRec,
+ int offset)
+{
+ Pen **penPtrPtr = (Pen **)(widgRec + offset);
+
+ if (*penPtrPtr != NULL) {
+ Blt_FreePen(*penPtrPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPen --
+ *
+ * Convert the color value into a string.
+ *
+ * Results:
+ * The string representing the symbol color is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPen(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* String representing pen */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags)
+{
+ Pen **penPtrPtr = (Pen **)(widgRec + offset);
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ if ((string[0] == '\0') && (flags & BLT_CONFIG_NULL_OK)) {
+ Blt_FreePen(*penPtrPtr);
+ *penPtrPtr = NULL;
+ } else {
+ Pen *penPtr;
+ Graph *graphPtr;
+ ClassId classId = (ClassId)clientData; /* Element type. */
+
+ graphPtr = Blt_GetGraphFromWindowData(tkwin);
+ assert(graphPtr);
+
+ if (classId == CID_NONE) {
+ classId = graphPtr->classId;
+ }
+ if (Blt_GetPenFromObj(interp, graphPtr, objPtr, classId, &penPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_FreePen(*penPtrPtr);
+ *penPtrPtr = penPtr;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PenToObj --
+ *
+ * Parse the name of the name.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PenToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* Widget information record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Pen *penPtr = *(Pen **)(widgRec + offset);
+
+ if (penPtr == NULL) {
+ return Tcl_NewStringObj("", -1);
+ } else {
+ return Tcl_NewStringObj(penPtr->name, -1);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetPenFromObj --
+ *
+ * Find and return the pen style from a given name.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+GetPenFromObj(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ Pen **penPtrPtr)
+{
+ Blt_HashEntry *hPtr;
+ Pen *penPtr;
+ const char *name;
+
+ penPtr = NULL;
+ name = Tcl_GetString(objPtr);
+ hPtr = Blt_FindHashEntry(&graphPtr->penTable, name);
+ if (hPtr != NULL) {
+ penPtr = Blt_GetHashValue(hPtr);
+ if (penPtr->flags & DELETE_PENDING) {
+ penPtr = NULL;
+ }
+ }
+ if (penPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find pen \"", name, "\" in \"",
+ Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ *penPtrPtr = penPtr;
+ return TCL_OK;
+}
+
+static void
+DestroyPen(Pen *penPtr)
+{
+ Graph *graphPtr = penPtr->graphPtr;
+
+ Blt_FreeOptions(penPtr->configSpecs, (char *)penPtr, graphPtr->display, 0);
+ (*penPtr->destroyProc) (graphPtr, penPtr);
+ if ((penPtr->name != NULL) && (penPtr->name[0] != '\0')) {
+ free((void*)(penPtr->name));
+ }
+ if (penPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&graphPtr->penTable, penPtr->hashPtr);
+ }
+ free(penPtr);
+}
+
+void
+Blt_FreePen(Pen *penPtr)
+{
+ if (penPtr != NULL) {
+ penPtr->refCount--;
+ if ((penPtr->refCount == 0) && (penPtr->flags & DELETE_PENDING)) {
+ DestroyPen(penPtr);
+ }
+ }
+}
+
+Pen *
+Blt_CreatePen(Graph *graphPtr, const char *penName, ClassId classId,
+ int objc, Tcl_Obj *const *objv)
+{
+ Pen *penPtr;
+ Blt_HashEntry *hPtr;
+ unsigned int configFlags;
+ int isNew;
+ int i;
+
+ /*
+ * Scan the option list for a "-type" entry. This will indicate what type
+ * of pen we are creating. Otherwise we'll default to the suggested type.
+ * Last -type option wins.
+ */
+ for (i = 0; i < objc; i += 2) {
+ char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objv[i], &length);
+ if ((length > 2) && (strncmp(string, "-type", length) == 0)) {
+ char *arg;
+
+ arg = Tcl_GetString(objv[i + 1]);
+ if (strcmp(arg, "bar") == 0) {
+ classId = CID_ELEM_BAR;
+ } else if (strcmp(arg, "line") == 0) {
+ classId = CID_ELEM_LINE;
+ } else {
+ Tcl_AppendResult(graphPtr->interp, "unknown pen type \"",
+ arg, "\" specified", (char *)NULL);
+ return NULL;
+ }
+ }
+ }
+ classId = CID_ELEM_LINE;
+ hPtr = Blt_CreateHashEntry(&graphPtr->penTable, penName, &isNew);
+ if (!isNew) {
+ penPtr = Blt_GetHashValue(hPtr);
+ if ((penPtr->flags & DELETE_PENDING) == 0) {
+ Tcl_AppendResult(graphPtr->interp, "pen \"", penName,
+ "\" already exists in \"", Tk_PathName(graphPtr->tkwin), "\"",
+ (char *)NULL);
+ return NULL;
+ }
+ if (penPtr->classId != classId) {
+ Tcl_AppendResult(graphPtr->interp, "pen \"", penName,
+ "\" in-use: can't change pen type from \"",
+ Blt_GraphClassName(penPtr->classId), "\" to \"",
+ Blt_GraphClassName(classId), "\"", (char *)NULL);
+ return NULL;
+ }
+ penPtr->flags &= ~DELETE_PENDING; /* Undelete the pen. */
+ } else {
+ if (classId == CID_ELEM_BAR) {
+ penPtr = Blt_BarPen(penName);
+ } else {
+ penPtr = Blt_LinePen(penName);
+ }
+ penPtr->classId = classId;
+ penPtr->hashPtr = hPtr;
+ penPtr->graphPtr = graphPtr;
+ Blt_SetHashValue(hPtr, penPtr);
+ }
+ configFlags = (penPtr->flags & (ACTIVE_PEN | NORMAL_PEN));
+ if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
+ penPtr->name, "Pen", penPtr->configSpecs, objc, objv,
+ (char *)penPtr, configFlags) != TCL_OK) {
+ if (isNew) {
+ DestroyPen(penPtr);
+ }
+ return NULL;
+ }
+ (*penPtr->configProc) (graphPtr, penPtr);
+ return penPtr;
+}
+
+int
+Blt_GetPenFromObj(Tcl_Interp *interp, Graph *graphPtr, Tcl_Obj *objPtr,
+ ClassId classId, Pen **penPtrPtr)
+{
+ Blt_HashEntry *hPtr;
+ Pen *penPtr;
+ const char *name;
+
+ penPtr = NULL;
+ name = Tcl_GetString(objPtr);
+ hPtr = Blt_FindHashEntry(&graphPtr->penTable, name);
+ if (hPtr != NULL) {
+ penPtr = Blt_GetHashValue(hPtr);
+ if (penPtr->flags & DELETE_PENDING) {
+ penPtr = NULL;
+ }
+ }
+ if (penPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find pen \"", name, "\" in \"",
+ Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ classId = CID_ELEM_LINE;
+ if (penPtr->classId != classId) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "pen \"", name,
+ "\" is the wrong type (is \"",
+ Blt_GraphClassName(penPtr->classId), "\"", ", wanted \"",
+ Blt_GraphClassName(classId), "\")", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ penPtr->refCount++;
+ *penPtrPtr = penPtr;
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DestroyPens --
+ *
+ * Release memory and resources allocated for the style.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the pen style is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DestroyPens(Graph *graphPtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->penTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Pen *penPtr;
+
+ penPtr = Blt_GetHashValue(hPtr);
+ penPtr->hashPtr = NULL;
+ DestroyPen(penPtr);
+ }
+ Blt_DeleteHashTable(&graphPtr->penTable);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ * Queries axis attributes (font, line width, label, etc).
+ *
+ * Results:
+ * A standard TCL result. If querying configuration values,
+ * interp->result will contain the results.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+CgetOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Pen *penPtr;
+ unsigned int configFlags;
+
+ if (GetPenFromObj(interp, graphPtr, objv[3], &penPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ configFlags = (penPtr->flags & (ACTIVE_PEN | NORMAL_PEN));
+ return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin,
+ penPtr->configSpecs, (char *)penPtr, objv[4], configFlags);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * Queries or resets pen attributes (font, line width, color, etc).
+ *
+ * Results:
+ * A standard TCL result. If querying configuration values,
+ * interp->result will contain the results.
+ *
+ * Side Effects:
+ * Pen resources are possibly allocated (GC, font).
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Pen *penPtr;
+ int nNames, nOpts;
+ int redraw;
+ Tcl_Obj *const *options;
+ int i;
+
+ /* Figure out where the option value pairs begin */
+ objc -= 3;
+ objv += 3;
+ for (i = 0; i < objc; i++) {
+ char *string;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ break;
+ }
+ if (GetPenFromObj(interp, graphPtr, objv[i], &penPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ nNames = i; /* Number of pen names specified */
+ nOpts = objc - i; /* Number of options specified */
+ options = objv + i; /* Start of options in objv */
+
+ redraw = 0;
+ for (i = 0; i < nNames; i++) {
+ int flags;
+
+ if (GetPenFromObj(interp, graphPtr, objv[i], &penPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ flags = BLT_CONFIG_OBJV_ONLY | (penPtr->flags&(ACTIVE_PEN|NORMAL_PEN));
+ if (nOpts == 0) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ penPtr->configSpecs, (char *)penPtr, (Tcl_Obj *)NULL, flags);
+ } else if (nOpts == 1) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin,
+ penPtr->configSpecs, (char *)penPtr, options[0], flags);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin,
+ penPtr->configSpecs, nOpts, options, (char *)penPtr, flags)
+ != TCL_OK) {
+ break;
+ }
+ (*penPtr->configProc) (graphPtr, penPtr);
+ if (penPtr->refCount > 0) {
+ redraw++;
+ }
+ }
+ if (redraw) {
+ graphPtr->flags |= CACHE_DIRTY;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ if (i < nNames) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateOp --
+ *
+ * Adds a new penstyle to the graph.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+CreateOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Pen *penPtr;
+
+ penPtr = Blt_CreatePen(graphPtr, Tcl_GetString(objv[3]), graphPtr->classId,
+ objc - 4, objv + 4);
+ if (penPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, objv[3]);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteOp --
+ *
+ * Delete the given pen.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp->result field is a list of the
+ * graph axis limits.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*ARGSUSED*/
+static int
+DeleteOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ Pen *penPtr;
+
+ if (GetPenFromObj(interp, graphPtr, objv[i], &penPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (penPtr->flags & DELETE_PENDING) {
+ Tcl_AppendResult(interp, "can't find pen \"",
+ Tcl_GetString(objv[i]), "\" in \"",
+ Tk_PathName(graphPtr->tkwin), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ penPtr->flags |= DELETE_PENDING;
+ if (penPtr->refCount == 0) {
+ DestroyPen(penPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NamesOp --
+ *
+ * Return a list of the names of all the axes.
+ *
+ * Results:
+ * Returns a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+NamesOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (objc == 3) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->penTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Pen *penPtr;
+
+ penPtr = Blt_GetHashValue(hPtr);
+ if ((penPtr->flags & DELETE_PENDING) == 0) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(penPtr->name, -1));
+ }
+ }
+ } else {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch iter;
+
+ for (hPtr = Blt_FirstHashEntry(&graphPtr->penTable, &iter);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&iter)) {
+ Pen *penPtr;
+
+ penPtr = Blt_GetHashValue(hPtr);
+ if ((penPtr->flags & DELETE_PENDING) == 0) {
+ int i;
+
+ for (i = 3; i < objc; i++) {
+ char *pattern;
+
+ pattern = Tcl_GetString(objv[i]);
+ if (Tcl_StringMatch(penPtr->name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(penPtr->name, -1));
+ break;
+ }
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TypeOp --
+ *
+ * Return the type of pen.
+ *
+ * Results:
+ * Returns a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TypeOp(Tcl_Interp *interp, Graph *graphPtr, int objc, Tcl_Obj *const *objv)
+{
+ Pen *penPtr;
+
+ if (GetPenFromObj(interp, graphPtr, objv[3], &penPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetStringObj(Tcl_GetObjResult(interp),
+ Blt_GraphClassName(penPtr->classId), -1);
+ return TCL_OK;
+}
+
+static Blt_OpSpec penOps[] =
+{
+ {"cget", 2, CgetOp, 5, 5, "penName option",},
+ {"configure", 2, ConfigureOp, 4, 0,
+ "penName ?penName?... ?option value?...",},
+ {"create", 2, CreateOp, 4, 0, "penName ?option value?...",},
+ {"delete", 2, DeleteOp, 3, 0, "?penName?...",},
+ {"names", 1, NamesOp, 3, 0, "?pattern?...",},
+ {"type", 1, TypeOp, 4, 4, "penName",},
+};
+static int nPenOps = sizeof(penOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_PenOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ GraphPenProc *proc;
+
+ proc = Blt_GetOpFromObj(interp, nPenOps, penOps, BLT_OP_ARG2,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ return (*proc) (interp, graphPtr, objc, objv);
+}
diff --git a/tlt3.0/bltGrPs.c b/tlt3.0/bltGrPs.c
new file mode 100644
index 0000000..eae049b
--- /dev/null
+++ b/tlt3.0/bltGrPs.c
@@ -0,0 +1,709 @@
+
+/*
+ * bltGrPs.c --
+ *
+ * This module implements the "postscript" operation for BLT graph widget.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PostScript routines to print a graph
+ *
+ *---------------------------------------------------------------------------
+ */
+#include <stdarg.h>
+#include <time.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltPsInt.h"
+
+#define MM_INCH 25.4
+#define PICA_INCH 72.0
+
+typedef int (GraphPsProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+static Blt_OptionParseProc ObjToPicaProc;
+static Blt_OptionPrintProc PicaToObjProc;
+static Blt_CustomOption picaOption =
+{
+ ObjToPicaProc, PicaToObjProc, NULL, (ClientData)0,
+};
+
+static Blt_OptionParseProc ObjToPad;
+static Blt_OptionPrintProc PadToObj;
+static Blt_CustomOption padOption =
+{
+ ObjToPad, PadToObj, NULL, (ClientData)0,
+};
+
+#define DEF_PS_CENTER "yes"
+#define DEF_PS_COLOR_MAP (char *)NULL
+#define DEF_PS_GREYSCALE "no"
+#define DEF_PS_DECORATIONS "no"
+#define DEF_PS_FONT_MAP (char *)NULL
+#define DEF_PS_FOOTER "no"
+#define DEF_PS_LEVEL "2"
+#define DEF_PS_HEIGHT "0"
+#define DEF_PS_LANDSCAPE "no"
+#define DEF_PS_PADX "1.0i"
+#define DEF_PS_PADY "1.0i"
+#define DEF_PS_PAPERHEIGHT "11.0i"
+#define DEF_PS_PAPERWIDTH "8.5i"
+#define DEF_PS_WIDTH "0"
+#define DEF_PS_COMMENTS ""
+
+static Blt_ConfigSpec configSpecs[] =
+{
+ {BLT_CONFIG_BITMASK, "-center", "center", "Center", DEF_PS_CENTER,
+ Blt_Offset(PageSetup, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)PS_CENTER},
+ {BLT_CONFIG_STRING, "-colormap", "colorMap", "ColorMap",
+ DEF_PS_COLOR_MAP, Blt_Offset(PageSetup, colorVarName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_LIST, "-comments", "comments", "Comments",
+ DEF_PS_COMMENTS, Blt_Offset(PageSetup, comments), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BITMASK, "-decorations", "decorations", "Decorations",
+ DEF_PS_DECORATIONS, Blt_Offset(PageSetup, flags),
+ BLT_CONFIG_DONT_SET_DEFAULT, (Blt_CustomOption *)PS_DECORATIONS},
+ {BLT_CONFIG_STRING, "-fontmap", "fontMap", "FontMap",
+ DEF_PS_FONT_MAP, Blt_Offset(PageSetup, fontVarName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BITMASK, "-footer", "footer", "Footer", DEF_PS_FOOTER,
+ Blt_Offset(PageSetup, flags), BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)PS_FOOTER},
+ {BLT_CONFIG_BITMASK, "-greyscale", "greyscale", "Greyscale",
+ DEF_PS_GREYSCALE, Blt_Offset(PageSetup, flags),
+ BLT_CONFIG_DONT_SET_DEFAULT, (Blt_CustomOption *)PS_GREYSCALE},
+ {BLT_CONFIG_CUSTOM, "-height", "height", "Height", DEF_PS_HEIGHT,
+ Blt_Offset(PageSetup, reqHeight), BLT_CONFIG_DONT_SET_DEFAULT,
+ &picaOption},
+ {BLT_CONFIG_BITMASK, "-landscape", "landscape", "Landscape",
+ DEF_PS_LANDSCAPE, Blt_Offset(PageSetup, flags),
+ BLT_CONFIG_DONT_SET_DEFAULT, (Blt_CustomOption *)PS_LANDSCAPE},
+ {BLT_CONFIG_INT_POS, "-level", "level", "Level", DEF_PS_LEVEL,
+ Blt_Offset(PageSetup, level), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_CUSTOM, "-padx", "padX", "PadX", DEF_PS_PADX,
+ Blt_Offset(PageSetup, xPad), 0, &padOption},
+ {BLT_CONFIG_CUSTOM, "-pady", "padY", "PadY", DEF_PS_PADY,
+ Blt_Offset(PageSetup, yPad), 0, &padOption},
+ {BLT_CONFIG_CUSTOM, "-paperheight", "paperHeight", "PaperHeight",
+ DEF_PS_PAPERHEIGHT, Blt_Offset(PageSetup, reqPaperHeight), 0,
+ &picaOption},
+ {BLT_CONFIG_CUSTOM, "-paperwidth", "paperWidth", "PaperWidth",
+ DEF_PS_PAPERWIDTH, Blt_Offset(PageSetup, reqPaperWidth), 0,
+ &picaOption},
+ {BLT_CONFIG_CUSTOM, "-width", "width", "Width", DEF_PS_WIDTH,
+ Blt_Offset(PageSetup, reqWidth), BLT_CONFIG_DONT_SET_DEFAULT,
+ &picaOption},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPicaProc --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPicaProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* New value. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int *picaPtr = (int *)(widgRec + offset);
+
+ return Blt_Ps_GetPicaFromObj(interp, objPtr, picaPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PicaToObj --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PicaToObjProc(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Not used. */
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* PostScript structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ int pica = *(int *)(widgRec + offset);
+
+ return Tcl_NewIntObj(pica);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToPad --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToPad(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tk_Window tkwin, /* Not used. */
+ Tcl_Obj *objPtr, /* New value. */
+ char *widgRec, /* Widget record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Blt_Pad *padPtr = (Blt_Pad *) (widgRec + offset);
+
+ return Blt_Ps_GetPadFromObj(interp, objPtr, padPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PadToObj --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static Tcl_Obj *
+PadToObj(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp,
+ Tk_Window tkwin, /* Not used. */
+ char *widgRec, /* PostScript structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Blt_Pad *padPtr = (Blt_Pad *)(widgRec + offset);
+ Tcl_Obj *objPtr, *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ objPtr = Tcl_NewIntObj(padPtr->side1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ objPtr = Tcl_NewIntObj(padPtr->side2);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ return listObjPtr;
+}
+
+static void
+AddComments(Blt_Ps ps, const char **comments)
+{
+ const char **p;
+
+ for (p = comments; *p != NULL; p += 2) {
+ if (*(p+1) == NULL) {
+ break;
+ }
+ Blt_Ps_Format(ps, "%% %s: %s\n", *p, *(p+1));
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PostScriptPreamble
+ *
+ * The PostScript preamble calculates the needed translation and scaling
+ * to make X11 coordinates compatible with PostScript.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+PostScriptPreamble(Graph *graphPtr, const char *fileName, Blt_Ps ps)
+{
+ PageSetup *setupPtr = graphPtr->pageSetup;
+ time_t ticks;
+ char date[200]; /* Holds the date string from ctime() */
+ char *newline;
+
+ if (fileName == NULL) {
+ fileName = Tk_PathName(graphPtr->tkwin);
+ }
+ Blt_Ps_Append(ps, "%!PS-Adobe-3.0 EPSF-3.0\n");
+
+ /*
+ * The "BoundingBox" comment is required for EPS files. The box
+ * coordinates are integers, so we need round away from the center of the
+ * box.
+ */
+ Blt_Ps_Format(ps, "%%%%BoundingBox: %d %d %d %d\n",
+ setupPtr->left, setupPtr->paperHeight - setupPtr->top,
+ setupPtr->right, setupPtr->paperHeight - setupPtr->bottom);
+
+ Blt_Ps_Append(ps, "%%Pages: 0\n");
+
+ Blt_Ps_Format(ps, "%%%%Creator: (%s %s %s)\n",
+ PACKAGE_NAME, PACKAGE_VERSION, Tk_Class(graphPtr->tkwin));
+
+ ticks = time((time_t *) NULL);
+ strcpy(date, ctime(&ticks));
+ newline = date + strlen(date) - 1;
+ if (*newline == '\n') {
+ *newline = '\0';
+ }
+ Blt_Ps_Format(ps, "%%%%CreationDate: (%s)\n", date);
+ Blt_Ps_Format(ps, "%%%%Title: (%s)\n", fileName);
+ Blt_Ps_Append(ps, "%%DocumentData: Clean7Bit\n");
+ if (setupPtr->flags & PS_LANDSCAPE) {
+ Blt_Ps_Append(ps, "%%Orientation: Landscape\n");
+ } else {
+ Blt_Ps_Append(ps, "%%Orientation: Portrait\n");
+ }
+ Blt_Ps_Append(ps, "%%DocumentNeededResources: font Helvetica Courier\n");
+ AddComments(ps, setupPtr->comments);
+ Blt_Ps_Append(ps, "%%EndComments\n\n");
+ if (Blt_Ps_IncludeFile(graphPtr->interp, ps, "bltGraph.pro") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (setupPtr->flags & PS_FOOTER) {
+ const char *who;
+
+ who = getenv("LOGNAME");
+ if (who == NULL) {
+ who = "???";
+ }
+ Blt_Ps_VarAppend(ps,
+ "8 /Helvetica SetFont\n",
+ "10 30 moveto\n",
+ "(Date: ", date, ") show\n",
+ "10 20 moveto\n",
+ "(File: ", fileName, ") show\n",
+ "10 10 moveto\n",
+ "(Created by: ", who, "@", Tcl_GetHostName(), ") show\n",
+ "0 0 moveto\n",
+ (char *)NULL);
+ }
+ /*
+ * Set the conversion from PostScript to X11 coordinates. Scale pica to
+ * pixels and flip the y-axis (the origin is the upperleft corner).
+ */
+ Blt_Ps_VarAppend(ps,
+ "% Transform coordinate system to use X11 coordinates\n\n",
+ "% 1. Flip y-axis over by reversing the scale,\n",
+ "% 2. Translate the origin to the other side of the page,\n",
+ "% making the origin the upper left corner\n", (char *)NULL);
+ Blt_Ps_Format(ps, "1 -1 scale\n");
+ /* Papersize is in pixels. Translate the new origin *after* changing the
+ * scale. */
+ Blt_Ps_Format(ps, "0 %d translate\n\n", -setupPtr->paperHeight);
+ Blt_Ps_VarAppend(ps, "% User defined page layout\n\n",
+ "% Set color level\n", (char *)NULL);
+ Blt_Ps_Format(ps, "%% Set origin\n%d %d translate\n\n",
+ setupPtr->left, setupPtr->bottom);
+ if (setupPtr->flags & PS_LANDSCAPE) {
+ Blt_Ps_Format(ps,
+ "%% Landscape orientation\n0 %g translate\n-90 rotate\n",
+ ((double)graphPtr->width * setupPtr->scale));
+ }
+ Blt_Ps_Append(ps, "\n%%EndSetup\n\n");
+ return TCL_OK;
+}
+
+
+static void
+MarginsToPostScript(Graph *graphPtr, Blt_Ps ps)
+{
+ PageSetup *setupPtr = graphPtr->pageSetup;
+ XRectangle margin[4];
+
+ margin[0].x = margin[0].y = margin[3].x = margin[1].x = 0;
+ margin[0].width = margin[3].width = graphPtr->width;
+ margin[0].height = graphPtr->top;
+ margin[3].y = graphPtr->bottom;
+ margin[3].height = graphPtr->height - graphPtr->bottom;
+ margin[2].y = margin[1].y = graphPtr->top;
+ margin[1].width = graphPtr->left;
+ margin[2].height = margin[1].height = graphPtr->bottom - graphPtr->top;
+ margin[2].x = graphPtr->right;
+ margin[2].width = graphPtr->width - graphPtr->right;
+
+ /* Clear the surrounding margins and clip the plotting surface */
+ if (setupPtr->flags & PS_DECORATIONS) {
+ Blt_Ps_XSetBackground(ps,Blt_BackgroundBorderColor(graphPtr->normalBg));
+ } else {
+ Blt_Ps_SetClearBackground(ps);
+ }
+ Blt_Ps_Append(ps, "% Margins\n");
+ Blt_Ps_XFillRectangles(ps, margin, 4);
+
+ Blt_Ps_Append(ps, "% Interior 3D border\n");
+ /* Interior 3D border */
+ if (graphPtr->plotBW > 0) {
+ Tk_3DBorder border;
+ int x, y, w, h;
+
+ x = graphPtr->left - graphPtr->plotBW;
+ y = graphPtr->top - graphPtr->plotBW;
+ w = (graphPtr->right - graphPtr->left) + (2*graphPtr->plotBW);
+ h = (graphPtr->bottom - graphPtr->top) + (2*graphPtr->plotBW);
+ border = Blt_BackgroundBorder(graphPtr->normalBg);
+ Blt_Ps_Draw3DRectangle(ps, border, (double)x, (double)y, w, h,
+ graphPtr->plotBW, graphPtr->plotRelief);
+ }
+ if (Blt_Legend_Site(graphPtr) & LEGEND_MARGIN_MASK) {
+ /*
+ * Print the legend if we're using a site which lies in one of the
+ * margins (left, right, top, or bottom) of the graph.
+ */
+ Blt_LegendToPostScript(graphPtr, ps);
+ }
+ if (graphPtr->title != NULL) {
+ Blt_Ps_Append(ps, "% Graph title\n");
+ Blt_Ps_DrawText(ps, graphPtr->title, &graphPtr->titleTextStyle,
+ (double)graphPtr->titleX, (double)graphPtr->titleY);
+ }
+ Blt_AxesToPostScript(graphPtr, ps);
+}
+
+
+static int
+GraphToPostScript(Graph *graphPtr, const char *ident, Blt_Ps ps)
+{
+ int x, y, w, h;
+ int result;
+ PageSetup *setupPtr = graphPtr->pageSetup;
+
+ /*
+ * We need to know how big a graph to print. If the graph hasn't been drawn
+ * yet, the width and height will be 1. Instead use the requested size of
+ * the widget. The user can still override this with the -width and -height
+ * postscript options.
+ */
+ if (setupPtr->reqWidth > 0) {
+ graphPtr->width = setupPtr->reqWidth;
+ } else if (graphPtr->width < 2) {
+ graphPtr->width = Tk_ReqWidth(graphPtr->tkwin);
+ }
+ if (setupPtr->reqHeight > 0) {
+ graphPtr->height = setupPtr->reqHeight;
+ } else if (graphPtr->height < 2) {
+ graphPtr->height = Tk_ReqHeight(graphPtr->tkwin);
+ }
+ Blt_Ps_ComputeBoundingBox(setupPtr, graphPtr->width, graphPtr->height);
+ graphPtr->flags |= LAYOUT_NEEDED | RESET_WORLD;
+
+ /* Turn on PostScript measurements when computing the graph's layout. */
+ Blt_Ps_SetPrinting(ps, TRUE);
+ Blt_ReconfigureGraph(graphPtr);
+ Blt_MapGraph(graphPtr);
+
+ result = PostScriptPreamble(graphPtr, ident, ps);
+ if (result != TCL_OK) {
+ goto error;
+ }
+ /* Determine rectangle of the plotting area for the graph window */
+ x = graphPtr->left - graphPtr->plotBW;
+ y = graphPtr->top - graphPtr->plotBW;
+
+ w = (graphPtr->right - graphPtr->left + 1) + (2*graphPtr->plotBW);
+ h = (graphPtr->bottom - graphPtr->top + 1) + (2*graphPtr->plotBW);
+
+ Blt_Ps_XSetFont(ps, Blt_Ts_GetFont(graphPtr->titleTextStyle));
+ if (graphPtr->pageSetup->flags & PS_DECORATIONS) {
+ Blt_Ps_XSetBackground(ps, Blt_BackgroundBorderColor(graphPtr->plotBg));
+ } else {
+ Blt_Ps_SetClearBackground(ps);
+ }
+ Blt_Ps_XFillRectangle(ps, x, y, w, h);
+ Blt_Ps_Rectangle(ps, x, y, w, h);
+ Blt_Ps_Append(ps, "gsave clip\n\n");
+ /* Draw the grid, elements, and markers in the plotting area. */
+ Blt_GridsToPostScript(graphPtr, ps);
+ Blt_MarkersToPostScript(graphPtr, ps, TRUE);
+ if ((Blt_Legend_Site(graphPtr) & LEGEND_PLOTAREA_MASK) &&
+ (!Blt_Legend_IsRaised(graphPtr))) {
+ /* Print legend underneath elements and markers */
+ Blt_LegendToPostScript(graphPtr, ps);
+ }
+ Blt_AxisLimitsToPostScript(graphPtr, ps);
+ Blt_ElementsToPostScript(graphPtr, ps);
+ if ((Blt_Legend_Site(graphPtr) & LEGEND_PLOTAREA_MASK) &&
+ (Blt_Legend_IsRaised(graphPtr))) {
+ /* Print legend above elements (but not markers) */
+ Blt_LegendToPostScript(graphPtr, ps);
+ }
+ Blt_MarkersToPostScript(graphPtr, ps, FALSE);
+ Blt_ActiveElementsToPostScript(graphPtr, ps);
+ Blt_Ps_VarAppend(ps, "\n",
+ "% Unset clipping\n",
+ "grestore\n\n", (char *)NULL);
+ MarginsToPostScript(graphPtr, ps);
+ Blt_Ps_VarAppend(ps,
+ "showpage\n",
+ "%Trailer\n",
+ "grestore\n",
+ "end\n",
+ "%EOF\n", (char *)NULL);
+ error:
+ /* Reset height and width of graph window */
+ graphPtr->width = Tk_Width(graphPtr->tkwin);
+ graphPtr->height = Tk_Height(graphPtr->tkwin);
+ graphPtr->flags |= MAP_WORLD;
+ Blt_Ps_SetPrinting(ps, FALSE);
+ Blt_ReconfigureGraph(graphPtr);
+ Blt_MapGraph(graphPtr);
+ /*
+ * Redraw the graph in order to re-calculate the layout as soon as
+ * possible. This is in the case the crosshairs are active.
+ */
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return result;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CgetOp --
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+CgetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ PageSetup *setupPtr = graphPtr->pageSetup;
+
+ if (Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)setupPtr, objv[3], 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureOp --
+ *
+ * This procedure is invoked to print the graph in a file.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * A new PostScript file is created.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ConfigureOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int flags = BLT_CONFIG_OBJV_ONLY;
+ PageSetup *setupPtr = graphPtr->pageSetup;
+
+ if (objc == 3) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)setupPtr, (Tcl_Obj *)NULL, flags);
+ } else if (objc == 4) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)setupPtr, objv[3], flags);
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc - 3, objv + 3, (char *)setupPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OutputOp --
+ *
+ * This procedure is invoked to print the graph in a file.
+ *
+ * Results:
+ * Standard TCL result. TCL_OK if plot was successfully printed,
+ * TCL_ERROR otherwise.
+ *
+ * Side effects:
+ * A new PostScript file is created.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+OutputOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ const char *buffer;
+ PostScript *psPtr;
+ Tcl_Channel channel;
+ const char *fileName; /* Name of file to write PostScript
+ * output If NULL, output is returned
+ * via interp->result. */
+ int length;
+
+ fileName = NULL; /* Used to identify the output sink. */
+ channel = NULL;
+ if (objc > 3) {
+ fileName = Tcl_GetString(objv[3]);
+ if (fileName[0] != '-') {
+ objv++, objc--; /* First argument is the file name. */
+ channel = Tcl_OpenFileChannel(interp, fileName, "w", 0666);
+ if (channel == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetChannelOption(interp, channel, "-translation", "binary")
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ psPtr = Blt_Ps_Create(graphPtr->interp, graphPtr->pageSetup);
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc - 3, objv + 3, (char *)graphPtr->pageSetup, BLT_CONFIG_OBJV_ONLY)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (GraphToPostScript(graphPtr, fileName, psPtr) != TCL_OK) {
+ goto error;
+ }
+ buffer = Blt_Ps_GetValue(psPtr, &length);
+ if (channel != NULL) {
+ int nBytes;
+ /*
+ * If a file name was given, write the results to that file
+ */
+ nBytes = Tcl_Write(channel, buffer, length);
+ if (nBytes < 0) {
+ Tcl_AppendResult(interp, "error writing file \"", fileName, "\": ",
+ Tcl_PosixError(interp), (char *)NULL);
+ goto error;
+ }
+ Tcl_Close(interp, channel);
+ } else {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), buffer, length);
+ }
+ Blt_Ps_Free(psPtr);
+ return TCL_OK;
+
+ error:
+ if (channel != NULL) {
+ Tcl_Close(interp, channel);
+ }
+ Blt_Ps_Free(psPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CreatePostScript --
+ *
+ * Creates a postscript structure.
+ *
+ * Results:
+ * Always TCL_OK.
+ *
+ * Side effects:
+ * A new PostScript structure is created.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_CreatePageSetup(Graph *graphPtr)
+{
+ PageSetup *setupPtr;
+
+ setupPtr = calloc(1, sizeof(PostScript));
+ setupPtr->flags = PS_CENTER;
+ setupPtr->level = 2;
+ graphPtr->pageSetup = setupPtr;
+
+ if (Blt_ConfigureComponentFromObj(graphPtr->interp, graphPtr->tkwin,
+ "postscript", "Postscript", configSpecs, 0, (Tcl_Obj **)NULL,
+ (char *)setupPtr, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_PostScriptOp --
+ *
+ * This procedure is invoked to process the TCL command that corresponds
+ * to a widget managed by this module. See the user documentation for
+ * details on what it does.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_OpSpec psOps[] =
+{
+ {"cget", 2, CgetOp, 4, 4, "option",},
+ {"configure", 2, ConfigureOp, 3, 0, "?option value?...",},
+ {"output", 1, OutputOp, 3, 0, "?fileName? ?option value?...",},
+};
+
+static int nPsOps = sizeof(psOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_PostScriptOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphPsProc *proc;
+ int result;
+
+ proc = Blt_GetOpFromObj(interp, nPsOps, psOps, BLT_OP_ARG2, objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ result = (*proc) (graphPtr, interp, objc, objv);
+ return result;
+}
+
+void
+Blt_DestroyPageSetup(Graph *graphPtr)
+{
+ if (graphPtr->pageSetup != NULL) {
+ Blt_FreeOptions(configSpecs, (char *)graphPtr->pageSetup,
+ graphPtr->display, 0);
+ free(graphPtr->pageSetup);
+ }
+}
diff --git a/tlt3.0/bltGraph.c b/tlt3.0/bltGraph.c
new file mode 100644
index 0000000..4959b79
--- /dev/null
+++ b/tlt3.0/bltGraph.c
@@ -0,0 +1,1762 @@
+
+/*
+ * bltGraph.c --
+ *
+ * This module implements a graph widget for the BLT toolkit.
+ *
+ * The graph widget was created by Sani Nassif and George Howlett.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * To do:
+ *
+ * 2) Update manual pages.
+ *
+ * 3) Update comments.
+ *
+ * 5) Surface, contour, and flow graphs
+ *
+ * 7) Arrows for line markers
+ *
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltGraph.h"
+#include "bltOp.h"
+#include "bltGrElem.h"
+#include "bltSwitch.h"
+
+typedef int (GraphCmdProc)(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+/*
+ * Objects in the graph have their own class names. These class names are
+ * used for the resource database and bindings. Example.
+ *
+ * option add *X.title "X Axis Title" widgetDefault
+ * .g marker bind BitmapMarker <Enter> { ... }
+ *
+ * The option database trick is performed by creating a temporary window when
+ * an object is initially configured. The class name of the temporary window
+ * will be from the list below.
+ */
+static const char *objectClassNames[] = {
+ "unknown",
+ "XAxis",
+ "YAxis",
+ "BarElement",
+ "ContourElement",
+ "LineElement",
+ "StripElement",
+ "BitmapMarker",
+ "ImageMarker",
+ "LineMarker",
+ "PolygonMarker",
+ "TextMarker",
+ "WindowMarker",
+};
+
+extern Blt_CustomOption bltLinePenOption;
+extern Blt_CustomOption bltBarPenOption;
+extern Blt_CustomOption bltBarModeOption;
+
+#define DEF_GRAPH_ASPECT_RATIO "0.0"
+#define DEF_GRAPH_BAR_BASELINE "0.0"
+#define DEF_GRAPH_BAR_MODE "normal"
+#define DEF_GRAPH_BAR_WIDTH "0.9"
+#define DEF_GRAPH_BACKGROUND STD_NORMAL_BACKGROUND
+#define DEF_GRAPH_BORDERWIDTH STD_BORDERWIDTH
+#define DEF_GRAPH_BUFFER_ELEMENTS "yes"
+#define DEF_GRAPH_BUFFER_GRAPH "1"
+#define DEF_GRAPH_CURSOR "crosshair"
+#define DEF_GRAPH_FONT "{Sans Serif} 12"
+#define DEF_GRAPH_HALO "2m"
+#define DEF_GRAPH_HALO_BAR "0.1i"
+#define DEF_GRAPH_HEIGHT "4i"
+#define DEF_GRAPH_HIGHLIGHT_BACKGROUND STD_NORMAL_BACKGROUND
+#define DEF_GRAPH_HIGHLIGHT_COLOR RGB_BLACK
+#define DEF_GRAPH_HIGHLIGHT_WIDTH "2"
+#define DEF_GRAPH_INVERT_XY "0"
+#define DEF_GRAPH_JUSTIFY "center"
+#define DEF_GRAPH_MARGIN "0"
+#define DEF_GRAPH_MARGIN_VAR (char *)NULL
+#define DEF_GRAPH_PLOT_BACKGROUND RGB_WHITE
+#define DEF_GRAPH_PLOT_BORDERWIDTH "1"
+#define DEF_GRAPH_PLOT_PADX "0"
+#define DEF_GRAPH_PLOT_PADY "0"
+#define DEF_GRAPH_PLOT_RELIEF "solid"
+#define DEF_GRAPH_RELIEF "flat"
+#define DEF_GRAPH_SHOW_VALUES "no"
+#define DEF_GRAPH_STACK_AXES "no"
+#define DEF_GRAPH_TAKE_FOCUS ""
+#define DEF_GRAPH_TITLE (char *)NULL
+#define DEF_GRAPH_TITLE_COLOR STD_NORMAL_FOREGROUND
+#define DEF_GRAPH_WIDTH "5i"
+#define DEF_GRAPH_DATA (char *)NULL
+#define DEF_GRAPH_DATA_COMMAND (char *)NULL
+#define DEF_GRAPH_UNMAP_HIDDEN_ELEMENTS "0"
+
+static Blt_ConfigSpec configSpecs[] =
+{
+ {BLT_CONFIG_FLOAT, "-aspect", "aspect", "Aspect", DEF_GRAPH_ASPECT_RATIO,
+ Blt_Offset(Graph, aspect), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BACKGROUND, "-background", "background", "Background",
+ DEF_GRAPH_BACKGROUND, Blt_Offset(Graph, normalBg), 0},
+ {BLT_CONFIG_CUSTOM, "-barmode", "barMode", "BarMode", DEF_GRAPH_BAR_MODE,
+ Blt_Offset(Graph, mode), BLT_CONFIG_DONT_SET_DEFAULT,
+ &bltBarModeOption},
+ {BLT_CONFIG_FLOAT, "-barwidth", "barWidth", "BarWidth",
+ DEF_GRAPH_BAR_WIDTH, Blt_Offset(Graph, barWidth), 0},
+ {BLT_CONFIG_FLOAT, "-baseline", "baseline", "Baseline",
+ DEF_GRAPH_BAR_BASELINE, Blt_Offset(Graph, baseline), 0},
+ {BLT_CONFIG_SYNONYM, "-bd", "borderWidth", (char *)NULL, (char *)NULL,0, 0},
+ {BLT_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_SYNONYM, "-bm", "bottomMargin", (char *)NULL, (char *)NULL,
+ 0, 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-borderwidth", "borderWidth", "BorderWidth",
+ DEF_GRAPH_BORDERWIDTH, Blt_Offset(Graph, borderWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-bottommargin", "bottomMargin", "Margin",
+ DEF_GRAPH_MARGIN, Blt_Offset(Graph, bottomMargin.reqSize), 0},
+ {BLT_CONFIG_STRING, "-bottomvariable", "bottomVariable", "BottomVariable",
+ DEF_GRAPH_MARGIN_VAR, Blt_Offset(Graph, bottomMargin.varName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_BOOLEAN, "-bufferelements", "bufferElements", "BufferElements",
+ DEF_GRAPH_BUFFER_ELEMENTS, Blt_Offset(Graph, backingStore),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BOOLEAN, "-buffergraph", "bufferGraph", "BufferGraph",
+ DEF_GRAPH_BUFFER_GRAPH, Blt_Offset(Graph, doubleBuffer),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_ACTIVE_CURSOR, "-cursor", "cursor", "Cursor",
+ DEF_GRAPH_CURSOR, Blt_Offset(Graph, cursor), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-data", "data", "Data",
+ (char *)NULL, Blt_Offset(Graph, data), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-datacommand", "dataCommand", "DataCommand",
+ (char *)NULL, Blt_Offset(Graph, dataCmd), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_SYNONYM, "-fg", "foreground", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_FONT, "-font", "font", "Font",
+ DEF_GRAPH_FONT, Blt_Offset(Graph, titleTextStyle.font), 0},
+ {BLT_CONFIG_COLOR, "-foreground", "foreground", "Foreground",
+ DEF_GRAPH_TITLE_COLOR, Blt_Offset(Graph, titleTextStyle.color), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-halo", "halo", "Halo", DEF_GRAPH_HALO,
+ Blt_Offset(Graph, halo), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-height", "height", "Height", DEF_GRAPH_HEIGHT,
+ Blt_Offset(Graph, reqHeight), 0},
+ {BLT_CONFIG_COLOR, "-highlightbackground", "highlightBackground",
+ "HighlightBackground", DEF_GRAPH_HIGHLIGHT_BACKGROUND,
+ Blt_Offset(Graph, highlightBgColor), 0},
+ {BLT_CONFIG_COLOR, "-highlightcolor", "highlightColor", "HighlightColor",
+ DEF_GRAPH_HIGHLIGHT_COLOR, Blt_Offset(Graph, highlightColor), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-highlightthickness", "highlightThickness",
+ "HighlightThickness", DEF_GRAPH_HIGHLIGHT_WIDTH,
+ Blt_Offset(Graph, highlightWidth), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_BITMASK, "-unmaphiddenelements", "unmapHiddenElements",
+ "UnmapHiddenElements", DEF_GRAPH_UNMAP_HIDDEN_ELEMENTS,
+ Blt_Offset(Graph, flags), ALL_GRAPHS | BLT_CONFIG_DONT_SET_DEFAULT,
+ (Blt_CustomOption *)UNMAP_HIDDEN},
+ {BLT_CONFIG_BOOLEAN, "-invertxy", "invertXY", "InvertXY",
+ DEF_GRAPH_INVERT_XY, Blt_Offset(Graph, inverted),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_JUSTIFY, "-justify", "justify", "Justify", DEF_GRAPH_JUSTIFY,
+ Blt_Offset(Graph, titleTextStyle.justify), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-leftmargin", "leftMargin", "Margin",
+ DEF_GRAPH_MARGIN, Blt_Offset(Graph, leftMargin.reqSize),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-leftvariable", "leftVariable", "LeftVariable",
+ DEF_GRAPH_MARGIN_VAR, Blt_Offset(Graph, leftMargin.varName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-lm", "leftMargin", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_BACKGROUND, "-plotbackground", "plotBackground", "Background",
+ DEF_GRAPH_PLOT_BACKGROUND, Blt_Offset(Graph, plotBg), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-plotborderwidth", "plotBorderWidth",
+ "PlotBorderWidth", DEF_GRAPH_PLOT_BORDERWIDTH,
+ Blt_Offset(Graph, plotBW), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PAD, "-plotpadx", "plotPadX", "PlotPad", DEF_GRAPH_PLOT_PADX,
+ Blt_Offset(Graph, xPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PAD, "-plotpady", "plotPadY", "PlotPad", DEF_GRAPH_PLOT_PADY,
+ Blt_Offset(Graph, yPad), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_RELIEF, "-plotrelief", "plotRelief", "Relief",
+ DEF_GRAPH_PLOT_RELIEF, Blt_Offset(Graph, plotRelief),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_RELIEF, "-relief", "relief", "Relief", DEF_GRAPH_RELIEF,
+ Blt_Offset(Graph, relief), BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-rightmargin", "rightMargin", "Margin",
+ DEF_GRAPH_MARGIN, Blt_Offset(Graph, rightMargin.reqSize),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-rightvariable", "rightVariable", "RightVariable",
+ DEF_GRAPH_MARGIN_VAR, Blt_Offset(Graph, rightMargin.varName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-rm", "rightMargin", (char *)NULL, (char *)NULL, 0,0},
+ {BLT_CONFIG_BOOLEAN, "-stackaxes", "stackAxes", "StackAxes",
+ DEF_GRAPH_STACK_AXES, Blt_Offset(Graph, stackAxes),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus",
+ DEF_GRAPH_TAKE_FOCUS, Blt_Offset(Graph, takeFocus), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_STRING, "-title", "title", "Title", DEF_GRAPH_TITLE,
+ Blt_Offset(Graph, title), BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_SYNONYM, "-tm", "topMargin", (char *)NULL, (char *)NULL, 0, 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-topmargin", "topMargin", "Margin",
+ DEF_GRAPH_MARGIN, Blt_Offset(Graph, topMargin.reqSize),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_STRING, "-topvariable", "topVariable", "TopVariable",
+ DEF_GRAPH_MARGIN_VAR, Blt_Offset(Graph, topMargin.varName),
+ BLT_CONFIG_NULL_OK},
+ {BLT_CONFIG_PIXELS_NNEG, "-width", "width", "Width", DEF_GRAPH_WIDTH,
+ Blt_Offset(Graph, reqWidth), 0},
+ {BLT_CONFIG_PIXELS_NNEG, "-plotwidth", "plotWidth", "PlotWidth",
+ (char *)NULL, Blt_Offset(Graph, reqPlotWidth),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_PIXELS_NNEG, "-plotheight", "plotHeight", "PlotHeight",
+ (char *)NULL, Blt_Offset(Graph, reqPlotHeight),
+ BLT_CONFIG_DONT_SET_DEFAULT},
+ {BLT_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0}
+};
+
+static Tcl_IdleProc DisplayGraph;
+static Tcl_FreeProc DestroyGraph;
+static Tk_EventProc GraphEventProc;
+Tcl_ObjCmdProc Blt_GraphInstCmdProc;
+
+static Blt_BindPickProc PickEntry;
+static Tcl_ObjCmdProc BarchartCmd;
+static Tcl_ObjCmdProc GraphCmd;
+static Tcl_CmdDeleteProc GraphInstCmdDeleteProc;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_UpdateGraph --
+ *
+ * Tells the Tk dispatcher to call the graph display routine at the next
+ * idle point. This request is made only if the window is displayed and
+ * no other redraw request is pending.
+ *
+ * Results: None.
+ *
+ * Side effects:
+ * The window is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_UpdateGraph(ClientData clientData)
+{
+ Graph *graphPtr = clientData;
+
+ graphPtr->flags |= REDRAW_WORLD;
+ if ((graphPtr->tkwin != NULL) && !(graphPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayGraph, graphPtr);
+ graphPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_EventuallyRedrawGraph --
+ *
+ * Tells the Tk dispatcher to call the graph display routine at the next
+ * idle point. This request is made only if the window is displayed and
+ * no other redraw request is pending.
+ *
+ * Results: None.
+ *
+ * Side effects:
+ * The window is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_EventuallyRedrawGraph(Graph *graphPtr)
+{
+ if ((graphPtr->tkwin != NULL) && !(graphPtr->flags & REDRAW_PENDING)) {
+ Tcl_DoWhenIdle(DisplayGraph, graphPtr);
+ graphPtr->flags |= REDRAW_PENDING;
+ }
+}
+
+const char *
+Blt_GraphClassName(ClassId classId)
+{
+ if ((classId >= CID_NONE) && (classId <= CID_MARKER_WINDOW)) {
+ return objectClassNames[classId];
+ }
+ return NULL;
+}
+
+void
+Blt_GraphSetObjectClass(GraphObj *graphObjPtr, ClassId classId)
+{
+ graphObjPtr->classId = classId;
+ graphObjPtr->className = Blt_GraphClassName(classId);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GraphEventProc --
+ *
+ * This procedure is invoked by the Tk dispatcher for various events on
+ * graphs.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * When the window gets deleted, internal structures get cleaned up.
+ * When it gets exposed, the graph is eventually redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+GraphEventProc(ClientData clientData, XEvent *eventPtr)
+{
+ Graph *graphPtr = clientData;
+
+ if (eventPtr->type == Expose) {
+ if (eventPtr->xexpose.count == 0) {
+ graphPtr->flags |= REDRAW_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ } else if ((eventPtr->type == FocusIn) || (eventPtr->type == FocusOut)) {
+ if (eventPtr->xfocus.detail != NotifyInferior) {
+ if (eventPtr->type == FocusIn) {
+ graphPtr->flags |= FOCUS;
+ } else {
+ graphPtr->flags &= ~FOCUS;
+ }
+ graphPtr->flags |= REDRAW_WORLD;
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+ } else if (eventPtr->type == DestroyNotify) {
+ if (graphPtr->tkwin != NULL) {
+ graphPtr->tkwin = NULL;
+ Tcl_DeleteCommandFromToken(graphPtr->interp, graphPtr->cmdToken);
+ }
+ if (graphPtr->flags & REDRAW_PENDING) {
+ Tcl_CancelIdleCall(DisplayGraph, graphPtr);
+ }
+ Tcl_EventuallyFree(graphPtr, DestroyGraph);
+ } else if (eventPtr->type == ConfigureNotify) {
+ graphPtr->flags |= (MAP_WORLD | REDRAW_WORLD);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GraphInstCmdDeleteProc --
+ *
+ * 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
+GraphInstCmdDeleteProc(ClientData clientData) /* Pointer to widget record. */
+{
+ Graph *graphPtr = clientData;
+
+ if (graphPtr->tkwin != NULL) { /* NULL indicates window has already
+ * been destroyed. */
+ Tk_Window tkwin;
+
+ tkwin = graphPtr->tkwin;
+ graphPtr->tkwin = NULL;
+ Tk_DestroyWindow(tkwin);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AdjustAxisPointers --
+ *
+ * Sets the axis pointers according to whether the axis is inverted on
+ * not. The axis sites are also reset.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+AdjustAxisPointers(Graph *graphPtr)
+{
+ if (graphPtr->inverted) {
+ graphPtr->leftMargin.axes = graphPtr->axisChain[0];
+ graphPtr->bottomMargin.axes = graphPtr->axisChain[1];
+ graphPtr->rightMargin.axes = graphPtr->axisChain[2];
+ graphPtr->topMargin.axes = graphPtr->axisChain[3];
+ } else {
+ graphPtr->leftMargin.axes = graphPtr->axisChain[1];
+ graphPtr->bottomMargin.axes = graphPtr->axisChain[0];
+ graphPtr->rightMargin.axes = graphPtr->axisChain[3];
+ graphPtr->topMargin.axes = graphPtr->axisChain[2];
+ }
+}
+
+static int
+InitPens(Graph *graphPtr)
+{
+ Blt_InitHashTable(&graphPtr->penTable, BLT_STRING_KEYS);
+ if (Blt_CreatePen(graphPtr, "activeLine", CID_ELEM_LINE, 0, NULL) == NULL) {
+ return TCL_ERROR;
+ }
+ if (Blt_CreatePen(graphPtr, "activeBar", CID_ELEM_BAR, 0, NULL) == NULL) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GraphTags --
+ *
+ * Sets the binding tags for a graph obj. This routine is called by Tk
+ * when an event occurs in the graph. It fills an array of pointers with
+ * bind tag addresses.
+ *
+ * The object addresses are strings hashed in one of two tag tables: one
+ * for elements and the another for markers. Note that there's only one
+ * binding table for elements and markers. [We don't want to trigger
+ * both a marker and element bind command for the same event.] But we
+ * don't want a marker and element with the same tag name to activate the
+ * others bindings. A tag "all" for markers should mean all markers, not
+ * all markers and elements. As a result, element and marker tags are
+ * stored in separate hash tables, which means we can't generate the same
+ * tag address for both an elements and marker, even if they have the
+ * same name.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * This information will be used by the binding code in bltUtil.c to
+ * determine what graph objects match the current event. The tags are
+ * placed in tagArr and *nTagsPtr is set with the number of tags found.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+void
+Blt_GraphTags(
+ Blt_BindTable table,
+ ClientData object,
+ ClientData context, /* Not used. */
+ Blt_List list)
+{
+ GraphObj *graphObjPtr;
+ MakeTagProc *tagProc;
+ Graph *graphPtr;
+
+ graphPtr = (Graph *)Blt_GetBindingData(table);
+
+ /*
+ * All graph objects (markers, elements, axes, etc) have the same starting
+ * fields in their structures, such as "classId", "name", "className", and
+ * "tags".
+ */
+ graphObjPtr = (GraphObj *)object;
+
+ switch (graphObjPtr->classId) {
+ case CID_ELEM_BAR:
+ case CID_ELEM_LINE:
+ tagProc = Blt_MakeElementTag;
+ break;
+ case CID_AXIS_X:
+ case CID_AXIS_Y:
+ tagProc = Blt_MakeAxisTag;
+ break;
+ case CID_MARKER_BITMAP:
+ case CID_MARKER_IMAGE:
+ case CID_MARKER_LINE:
+ case CID_MARKER_POLYGON:
+ case CID_MARKER_TEXT:
+ case CID_MARKER_WINDOW:
+ tagProc = Blt_MakeMarkerTag;
+ break;
+ case CID_NONE:
+ Blt_Panic("unknown object type");
+ tagProc = NULL;
+ break;
+ default:
+ Blt_Panic("bogus object type");
+ tagProc = NULL;
+ break;
+ }
+ assert(graphObjPtr->name != NULL);
+
+ /* Always add the name of the object to the tag array. */
+ Blt_List_Append(list, (*tagProc)(graphPtr, graphObjPtr->name), 0);
+ Blt_List_Append(list, (*tagProc)(graphPtr, graphObjPtr->className), 0);
+ if (graphObjPtr->tags != NULL) {
+ const char **p;
+
+ for (p = graphObjPtr->tags; *p != NULL; p++) {
+ Blt_List_Append(list, (*tagProc) (graphPtr, *p), 0);
+ }
+ }
+}
+
+/*
+ * Find the closest point from the set of displayed elements, searching
+ * the display list from back to front. That way, if the points from
+ * two different elements overlay each other exactly, the one that's on
+ * top (visible) is picked.
+ */
+/*ARGSUSED*/
+static ClientData
+PickEntry(ClientData clientData, int x, int y, ClientData *contextPtr)
+{
+ Graph *graphPtr = clientData;
+ Blt_ChainLink link;
+ Element *elemPtr;
+ Marker *markerPtr;
+ Region2d exts;
+
+ if (graphPtr->flags & MAP_ALL) {
+ return NULL; /* Don't pick anything until the next
+ * redraw occurs. */
+ }
+ Blt_GraphExtents(graphPtr, &exts);
+
+ if ((x >= exts.right) || (x < exts.left) ||
+ (y >= exts.bottom) || (y < exts.top)) {
+ /*
+ * Sample coordinate is in one of the graph margins. Can only pick an
+ * axis.
+ */
+ return Blt_NearestAxis(graphPtr, x, y);
+ }
+ /*
+ * From top-to-bottom check:
+ * 1. markers drawn on top (-under false).
+ * 2. elements using its display list back to front.
+ * 3. markers drawn under element (-under true).
+ */
+ markerPtr = Blt_NearestMarker(graphPtr, x, y, FALSE);
+ if (markerPtr != NULL) {
+ return markerPtr; /* Found a marker (-under false). */
+ }
+ {
+ ClosestSearch search;
+
+ search.along = SEARCH_BOTH;
+ search.halo = graphPtr->halo;
+ search.index = -1;
+ search.x = x;
+ search.y = y;
+ search.dist = (double)(search.halo + 1);
+ search.mode = SEARCH_AUTO;
+
+ for (link = Blt_Chain_LastLink(graphPtr->elements.displayList);
+ link != NULL; link = Blt_Chain_PrevLink(link)) {
+ elemPtr = Blt_Chain_GetValue(link);
+ if (elemPtr->flags & (HIDE|MAP_ITEM)) {
+ continue;
+ }
+ if (elemPtr->state == STATE_NORMAL) {
+ (*elemPtr->procsPtr->closestProc) (graphPtr, elemPtr, &search);
+ }
+ }
+ if (search.dist <= (double)search.halo) {
+ return search.elemPtr; /* Found an element within the minimum
+ * halo distance. */
+ }
+ }
+ markerPtr = Blt_NearestMarker(graphPtr, x, y, TRUE);
+ if (markerPtr != NULL) {
+ return markerPtr; /* Found a marker (-under true) */
+ }
+ return NULL; /* Nothing found. */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ConfigureGraph --
+ *
+ * Allocates resources for the graph.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Configuration information, such as text string, colors, font, etc. get
+ * set for graphPtr; old resources get freed, if there were any. The
+ * graph is redisplayed.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+ConfigureGraph(Graph *graphPtr)
+{
+ XColor *colorPtr;
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+
+ /* Don't allow negative bar widths. Reset to an arbitrary value (0.1) */
+ if (graphPtr->barWidth <= 0.0f) {
+ graphPtr->barWidth = 0.8f;
+ }
+ graphPtr->inset = graphPtr->borderWidth + graphPtr->highlightWidth;
+ if ((graphPtr->reqHeight != Tk_ReqHeight(graphPtr->tkwin)) ||
+ (graphPtr->reqWidth != Tk_ReqWidth(graphPtr->tkwin))) {
+ Tk_GeometryRequest(graphPtr->tkwin, graphPtr->reqWidth,
+ graphPtr->reqHeight);
+ }
+ Tk_SetInternalBorder(graphPtr->tkwin, graphPtr->borderWidth);
+ colorPtr = Blt_BackgroundBorderColor(graphPtr->normalBg);
+
+ graphPtr->titleWidth = graphPtr->titleHeight = 0;
+ if (graphPtr->title != NULL) {
+ unsigned int w, h;
+
+ Blt_Ts_GetExtents(&graphPtr->titleTextStyle, graphPtr->title, &w, &h);
+ graphPtr->titleHeight = h;
+ }
+
+ /*
+ * Create GCs for interior and exterior regions, and a background GC for
+ * clearing the margins with XFillRectangle
+ */
+
+ /* Margin GC */
+
+ gcValues.foreground =
+ Blt_Ts_GetForeground(graphPtr->titleTextStyle)->pixel;
+ gcValues.background = colorPtr->pixel;
+ gcMask = (GCForeground | GCBackground);
+ newGC = Tk_GetGC(graphPtr->tkwin, gcMask, &gcValues);
+ if (graphPtr->drawGC != NULL) {
+ Tk_FreeGC(graphPtr->display, graphPtr->drawGC);
+ }
+ graphPtr->drawGC = newGC;
+
+ if (graphPtr->plotBg != NULL) {
+ Blt_SetBackgroundChangedProc(graphPtr->plotBg, Blt_UpdateGraph,
+ graphPtr);
+ }
+ if (graphPtr->normalBg != NULL) {
+ Blt_SetBackgroundChangedProc(graphPtr->normalBg, Blt_UpdateGraph,
+ graphPtr);
+ }
+ if (Blt_ConfigModified(configSpecs, "-invertxy", (char *)NULL)) {
+
+ /*
+ * If the -inverted option changed, we need to readjust the pointers
+ * to the axes and recompute the their scales.
+ */
+
+ AdjustAxisPointers(graphPtr);
+ graphPtr->flags |= RESET_AXES;
+ }
+ if ((!graphPtr->backingStore) && (graphPtr->cache != None)) {
+ /*
+ * Free the pixmap if we're not buffering the display of elements
+ * anymore.
+ */
+ Tk_FreePixmap(graphPtr->display, graphPtr->cache);
+ graphPtr->cache = None;
+ }
+ /*
+ * Reconfigure the crosshairs, just in case the background color of the
+ * plotarea has been changed.
+ */
+ Blt_ConfigureCrosshairs(graphPtr);
+
+ /*
+ * Update the layout of the graph (and redraw the elements) if any of the
+ * following graph options which affect the size of * the plotting area
+ * has changed.
+ *
+ * -aspect
+ * -borderwidth, -plotborderwidth
+ * -font, -title
+ * -width, -height
+ * -invertxy
+ * -bottommargin, -leftmargin, -rightmargin, -topmargin,
+ * -barmode, -barwidth
+ */
+ if (Blt_ConfigModified(configSpecs, "-invertxy", "-title", "-font",
+ "-*margin", "-*width", "-height", "-barmode", "-*pad*",
+ "-aspect", "-*borderwidth", "-plot*", "-*width", "-*height",
+ "-unmaphiddenelements", (char *)NULL)) {
+ graphPtr->flags |= RESET_WORLD | CACHE_DIRTY;
+ }
+ if (Blt_ConfigModified(configSpecs, "-plot*", "-*background",
+ (char *)NULL)) {
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ graphPtr->flags |= REDRAW_WORLD;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DestroyGraph --
+ *
+ * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release to
+ * clean up the internal structure of a graph at a safe time (when no-one
+ * is using it anymore).
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Everything associated with the widget is freed up.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void DestroyGraph(char* dataPtr)
+{
+ Graph *graphPtr = (Graph *)dataPtr;
+
+ Blt_FreeOptions(configSpecs, (char *)graphPtr, graphPtr->display, 0);
+ /*
+ * Destroy the individual components of the graph: elements, markers,
+ * axes, legend, display lists etc. Be careful to remove them in
+ * order. For example, axes are used by elements and markers, so they have
+ * to be removed after the markers and elements. Same it true with the
+ * legend and pens (they use elements), so can't be removed until the
+ * elements are destroyed.
+ */
+ Blt_DestroyMarkers(graphPtr);
+ Blt_DestroyElements(graphPtr);
+ Blt_DestroyLegend(graphPtr);
+ Blt_DestroyAxes(graphPtr);
+ Blt_DestroyPens(graphPtr);
+ Blt_DestroyCrosshairs(graphPtr);
+ Blt_DestroyPageSetup(graphPtr);
+ Blt_DestroyBarSets(graphPtr);
+ if (graphPtr->bindTable != NULL) {
+ Blt_DestroyBindingTable(graphPtr->bindTable);
+ }
+
+ /* Release allocated X resources and memory. */
+ if (graphPtr->drawGC != NULL) {
+ Tk_FreeGC(graphPtr->display, graphPtr->drawGC);
+ }
+ Blt_Ts_FreeStyle(graphPtr->display, &graphPtr->titleTextStyle);
+ if (graphPtr->cache != None) {
+ Tk_FreePixmap(graphPtr->display, graphPtr->cache);
+ }
+ free(graphPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * CreateGraph --
+ *
+ * This procedure creates and initializes a new widget.
+ *
+ * Results:
+ * The return value is a pointer to a structure describing the new
+ * widget. If an error occurred, then the return value is NULL and an
+ * error message is left in interp->result.
+ *
+ * Side effects:
+ * Memory is allocated, a Tk_Window is created, etc.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static Graph *
+CreateGraph(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, ClassId classId)
+{
+ Graph *graphPtr;
+ Tk_Window tkwin;
+
+ tkwin = Tk_CreateWindowFromPath(interp, Tk_MainWindow(interp),
+ Tcl_GetString(objv[1]), (char *)NULL);
+ if (tkwin == NULL) {
+ return NULL;
+ }
+ graphPtr = calloc(1, sizeof(Graph));
+
+ /* Initialize the graph data structure. */
+
+ graphPtr->tkwin = tkwin;
+ graphPtr->display = Tk_Display(tkwin);
+ graphPtr->interp = interp;
+ graphPtr->classId = classId;
+ graphPtr->backingStore = TRUE;
+ graphPtr->doubleBuffer = TRUE;
+ graphPtr->borderWidth = 2;
+ graphPtr->plotBW = 1;
+ graphPtr->highlightWidth = 2;
+ graphPtr->plotRelief = TK_RELIEF_SOLID;
+ graphPtr->relief = TK_RELIEF_FLAT;
+ graphPtr->flags = RESET_WORLD;
+ graphPtr->nextMarkerId = 1;
+ graphPtr->padLeft = graphPtr->padRight = 0;
+ graphPtr->padTop = graphPtr->padBottom = 0;
+ graphPtr->bottomMargin.site = MARGIN_BOTTOM;
+ graphPtr->leftMargin.site = MARGIN_LEFT;
+ graphPtr->topMargin.site = MARGIN_TOP;
+ graphPtr->rightMargin.site = MARGIN_RIGHT;
+ Blt_Ts_InitStyle(graphPtr->titleTextStyle);
+ Blt_Ts_SetAnchor(graphPtr->titleTextStyle, TK_ANCHOR_N);
+
+ Blt_InitHashTable(&graphPtr->axes.table, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->axes.tagTable, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->elements.table, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->elements.tagTable, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->markers.table, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->markers.tagTable, BLT_STRING_KEYS);
+ Blt_InitHashTable(&graphPtr->dataTables, BLT_STRING_KEYS);
+ graphPtr->elements.displayList = Blt_Chain_Create();
+ graphPtr->markers.displayList = Blt_Chain_Create();
+ graphPtr->axes.displayList = Blt_Chain_Create();
+
+ switch (classId) {
+ case CID_ELEM_LINE:
+ Tk_SetClass(tkwin, "Graph");
+ break;
+ case CID_ELEM_BAR:
+ Tk_SetClass(tkwin, "Barchart");
+ break;
+ default:
+ Tk_SetClass(tkwin, "???");
+ break;
+ }
+ Blt_SetWindowInstanceData(tkwin, graphPtr);
+
+ if (InitPens(graphPtr) != TCL_OK) {
+ goto error;
+ }
+ if (Blt_ConfigureWidgetFromObj(interp, tkwin, configSpecs, objc - 2,
+ objv + 2, (char *)graphPtr, 0) != TCL_OK) {
+ goto error;
+ }
+ if (Blt_DefaultAxes(graphPtr) != TCL_OK) {
+ goto error;
+ }
+ AdjustAxisPointers(graphPtr);
+
+ if (Blt_CreatePageSetup(graphPtr) != TCL_OK) {
+ goto error;
+ }
+ if (Blt_CreateCrosshairs(graphPtr) != TCL_OK) {
+ goto error;
+ }
+ if (Blt_CreateLegend(graphPtr) != TCL_OK) {
+ goto error;
+ }
+ Tk_CreateEventHandler(graphPtr->tkwin,
+ ExposureMask | StructureNotifyMask | FocusChangeMask, GraphEventProc,
+ graphPtr);
+
+ graphPtr->cmdToken = Tcl_CreateObjCommand(interp, Tcl_GetString(objv[1]),
+ Blt_GraphInstCmdProc, graphPtr, GraphInstCmdDeleteProc);
+ ConfigureGraph(graphPtr);
+ graphPtr->bindTable = Blt_CreateBindingTable(interp, tkwin, graphPtr,
+ PickEntry, Blt_GraphTags);
+
+ Tcl_SetObjResult(interp, objv[1]);
+ return graphPtr;
+
+ error:
+ DestroyGraph((char*)graphPtr);
+ return NULL;
+}
+
+/* Widget sub-commands */
+
+/*ARGSUSED*/
+static int
+XAxisOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int margin;
+
+ margin = (graphPtr->inverted) ? MARGIN_LEFT : MARGIN_BOTTOM;
+ return Blt_AxisOp(interp, graphPtr, margin, objc, objv);
+}
+
+static int
+X2AxisOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int margin;
+
+ margin = (graphPtr->inverted) ? MARGIN_RIGHT : MARGIN_TOP;
+ return Blt_AxisOp(interp, graphPtr, margin, objc, objv);
+}
+
+static int
+YAxisOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int margin;
+
+ margin = (graphPtr->inverted) ? MARGIN_BOTTOM : MARGIN_LEFT;
+ return Blt_AxisOp(interp, graphPtr, margin, objc, objv);
+}
+
+static int
+Y2AxisOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int margin;
+
+ margin = (graphPtr->inverted) ? MARGIN_TOP : MARGIN_RIGHT;
+ return Blt_AxisOp(interp, graphPtr, margin, objc, objv);
+}
+
+static int
+BarOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ return Blt_ElementOp(graphPtr, interp, objc, objv, CID_ELEM_BAR);
+}
+
+/*ARGSUSED*/
+static int
+LineOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ return Blt_ElementOp(graphPtr, interp, objc, objv, CID_ELEM_LINE);
+}
+
+static int
+ElementOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ return Blt_ElementOp(graphPtr, interp, objc, objv, graphPtr->classId);
+}
+
+static int
+ConfigureOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int flags;
+
+ flags = BLT_CONFIG_OBJV_ONLY;
+ if (objc == 2) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)graphPtr, (Tcl_Obj *)NULL, flags);
+ } else if (objc == 3) {
+ return Blt_ConfigureInfoFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)graphPtr, objv[2], flags);
+ } else {
+ if (Blt_ConfigureWidgetFromObj(interp, graphPtr->tkwin, configSpecs,
+ objc - 2, objv + 2, (char *)graphPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ConfigureGraph(graphPtr);
+ Blt_EventuallyRedrawGraph(graphPtr);
+ return TCL_OK;
+ }
+}
+
+/* ARGSUSED*/
+static int
+CgetOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ return Blt_ConfigureValueFromObj(interp, graphPtr->tkwin, configSpecs,
+ (char *)graphPtr, objv[2], 0);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ExtentsOp --
+ *
+ * Reports the size of one of several items within the graph. The
+ * following are valid items:
+ *
+ * "bottommargin" Height of the bottom margin
+ * "leftmargin" Width of the left margin
+ * "legend" x y w h of the legend
+ * "plotarea" x y w h of the plotarea
+ * "plotheight" Height of the plot area
+ * "rightmargin" Width of the right margin
+ * "topmargin" Height of the top margin
+ * "plotwidth" Width of the plot area
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED*/
+static int
+ExtentsOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ const char *string;
+ char c;
+ int length;
+
+ string = Tcl_GetStringFromObj(objv[2], &length);
+ c = string[0];
+ if ((c == 'p') && (length > 4) &&
+ (strncmp("plotheight", string, length) == 0)) {
+ int height;
+
+ height = graphPtr->bottom - graphPtr->top + 1;
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), height);
+ } else if ((c == 'p') && (length > 4) &&
+ (strncmp("plotwidth", string, length) == 0)) {
+ int width;
+
+ width = graphPtr->right - graphPtr->left + 1;
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), width);
+ } else if ((c == 'p') && (length > 4) &&
+ (strncmp("plotarea", string, length) == 0)) {
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(graphPtr->left));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(graphPtr->top));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(graphPtr->right - graphPtr->left + 1));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(graphPtr->bottom - graphPtr->top + 1));
+ Tcl_SetObjResult(interp, listObjPtr);
+ } else if ((c == 'l') && (length > 2) &&
+ (strncmp("legend", string, length) == 0)) {
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(Blt_Legend_X(graphPtr)));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(Blt_Legend_Y(graphPtr)));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(Blt_Legend_Width(graphPtr)));
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(Blt_Legend_Height(graphPtr)));
+ Tcl_SetObjResult(interp, listObjPtr);
+ } else if ((c == 'l') && (length > 2) &&
+ (strncmp("leftmargin", string, length) == 0)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), graphPtr->leftMargin.width);
+ } else if ((c == 'r') && (length > 1) &&
+ (strncmp("rightmargin", string, length) == 0)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), graphPtr->rightMargin.width);
+ } else if ((c == 't') && (length > 1) &&
+ (strncmp("topmargin", string, length) == 0)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), graphPtr->topMargin.height);
+ } else if ((c == 'b') && (length > 1) &&
+ (strncmp("bottommargin", string, length) == 0)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), graphPtr->bottomMargin.height);
+ } else {
+ Tcl_AppendResult(interp, "bad extent item \"", objv[2],
+ "\": should be plotheight, plotwidth, leftmargin, rightmargin, \
+topmargin, bottommargin, plotarea, or legend", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InsideOp --
+ *
+ * Returns true of false whether the given point is inside the plotting
+ * area (defined by left,bottom right, top).
+ *
+ * Results:
+ * Always returns TCL_OK. interp->result will contain the boolean string
+ * representation.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED*/
+static int
+InsideOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int x, y;
+ Region2d exts;
+ int result;
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_GraphExtents(graphPtr, &exts);
+ result = PointInRegion(&exts, x, y);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), result);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InvtransformOp --
+ *
+ * This procedure returns a list of the graph coordinate values
+ * corresponding with the given window X and Y coordinate positions.
+ *
+ * Results:
+ * Returns a standard TCL result. If an error occurred while parsing the
+ * window positions, TCL_ERROR is returned, and interp->result will
+ * contain the error message. Otherwise interp->result will contain a
+ * Tcl list of the x and y coordinates.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+InvtransformOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ double x, y;
+ Point2d point;
+ Axis2d axes;
+ Tcl_Obj *listObjPtr;
+
+ if ((Blt_ExprDoubleFromObj(interp, objv[2], &x) != TCL_OK) ||
+ (Blt_ExprDoubleFromObj(interp, objv[3], &y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ /* Perform the reverse transformation, converting from window coordinates
+ * to graph data coordinates. Note that the point is always mapped to the
+ * bottom and left axes (which may not be what the user wants). */
+
+ /* Pick the first pair of axes */
+ axes.x = Blt_GetFirstAxis(graphPtr->axisChain[0]);
+ axes.y = Blt_GetFirstAxis(graphPtr->axisChain[1]);
+ point = Blt_InvMap2D(graphPtr, x, y, &axes);
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(point.x));
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(point.y));
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TransformOp --
+ *
+ * This procedure returns a list of the window coordinates corresponding
+ * with the given graph x and y coordinates.
+ *
+ * Results:
+ * Returns a standard TCL result. interp->result contains the list of
+ * the graph coordinates. If an error occurred while parsing the window
+ * positions, TCL_ERROR is returned, then interp->result will contain an
+ * error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+TransformOp(Graph *graphPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ double x, y;
+ Point2d point;
+ Axis2d axes;
+ Tcl_Obj *listObjPtr;
+
+ if ((Blt_ExprDoubleFromObj(interp, objv[2], &x) != TCL_OK) ||
+ (Blt_ExprDoubleFromObj(interp, objv[3], &y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ /*
+ * Perform the transformation from window to graph coordinates. Note that
+ * the points are always mapped onto the bottom and left axes (which may
+ * not be the what the user wants).
+ */
+ axes.x = Blt_GetFirstAxis(graphPtr->axisChain[0]);
+ axes.y = Blt_GetFirstAxis(graphPtr->axisChain[1]);
+
+ point = Blt_Map2D(graphPtr, x, y, &axes);
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewIntObj(ROUND(point.x)));
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewIntObj(ROUND(point.y)));
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GraphWidgetCmd --
+ *
+ * This procedure is invoked to process the TCL command that
+ * corresponds to a widget managed by this module. See the user
+ * documentation for details on what it does.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_OpSpec graphOps[] =
+{
+ {"axis", 1, Blt_VirtualAxisOp, 2, 0, "oper ?args?",},
+ {"bar", 2, BarOp, 2, 0, "oper ?args?",},
+ {"cget", 2, CgetOp, 3, 3, "option",},
+ {"configure", 2, ConfigureOp, 2, 0, "?option value?...",},
+ {"crosshairs", 2, Blt_CrosshairsOp, 2, 0, "oper ?args?",},
+ {"element", 2, ElementOp, 2, 0, "oper ?args?",},
+ {"extents", 2, ExtentsOp, 3, 3, "item",},
+ {"inside", 3, InsideOp, 4, 4, "winX winY",},
+ {"invtransform", 3, InvtransformOp, 4, 4, "winX winY",},
+ {"legend", 2, Blt_LegendOp, 2, 0, "oper ?args?",},
+ {"line", 2, LineOp, 2, 0, "oper ?args?",},
+ {"marker", 2, Blt_MarkerOp, 2, 0, "oper ?args?",},
+ {"pen", 2, Blt_PenOp, 2, 0, "oper ?args?",},
+ {"postscript", 2, Blt_PostScriptOp, 2, 0, "oper ?args?",},
+ {"transform", 1, TransformOp, 4, 4, "x y",},
+ {"x2axis", 2, X2AxisOp, 2, 0, "oper ?args?",},
+ {"xaxis", 2, XAxisOp, 2, 0, "oper ?args?",},
+ {"y2axis", 2, Y2AxisOp, 2, 0, "oper ?args?",},
+ {"yaxis", 2, YAxisOp, 2, 0, "oper ?args?",},
+};
+static int nGraphOps = sizeof(graphOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_GraphInstCmdProc(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ GraphCmdProc *proc;
+ int result;
+ Graph *graphPtr = clientData;
+
+ proc = Blt_GetOpFromObj(interp, nGraphOps, graphOps, BLT_OP_ARG1,
+ objc, objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_Preserve(graphPtr);
+ result = (*proc) (graphPtr, interp, objc, objv);
+ Tcl_Release(graphPtr);
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NewGraph --
+ *
+ * Creates a new window and TCL command representing an instance of a
+ * graph widget.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+NewGraph(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv, ClassId classId)
+{
+ Graph *graphPtr;
+
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetString(objv[0]), " pathName ?option value?...\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ graphPtr = CreateGraph(interp, objc, objv, classId);
+ if (graphPtr == NULL) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GraphCmd --
+ *
+ * Creates a new window and TCL command representing an instance of a
+ * graph widget.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+GraphCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ return NewGraph(interp, objc, objv, CID_ELEM_LINE);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BarchartCmd --
+ *
+ * Creates a new window and TCL command representing an instance of a
+ * barchart widget.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+BarchartCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ return NewGraph(interp, objc, objv, CID_ELEM_BAR);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawMargins --
+ *
+ * Draws the exterior region of the graph (axes, ticks, titles, etc)
+ * onto a pixmap. The interior region is defined by the given rectangle
+ * structure.
+ *
+ * ---------------------------------
+ * | |
+ * | rectArr[0] |
+ * | |
+ * ---------------------------------
+ * | |top right| |
+ * | | | |
+ * | | | |
+ * | [1] | | [2] |
+ * | | | |
+ * | | | |
+ * | | | |
+ * | | | |
+ * | | | |
+ * | |left bottom| |
+ * ---------------------------------
+ * | |
+ * | rectArr[3] |
+ * | |
+ * ---------------------------------
+ *
+ * X coordinate axis
+ * Y coordinate axis
+ * legend
+ * interior border
+ * exterior border
+ * titles (X and Y axis, graph)
+ *
+ * Returns:
+ * None.
+ *
+ * Side Effects:
+ * Exterior of graph is displayed in its window.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawMargins(Graph *graphPtr, Drawable drawable)
+{
+ XRectangle rects[4];
+ int site;
+
+ /*
+ * Draw the four outer rectangles which encompass the plotting
+ * surface. This clears the surrounding area and clips the plot.
+ */
+ rects[0].x = rects[0].y = rects[3].x = rects[1].x = 0;
+ rects[0].width = rects[3].width = (short int)graphPtr->width;
+ rects[0].height = (short int)graphPtr->top;
+ rects[3].y = graphPtr->bottom;
+ rects[3].height = graphPtr->height - graphPtr->bottom;
+ rects[2].y = rects[1].y = graphPtr->top;
+ rects[1].width = graphPtr->left;
+ rects[2].height = rects[1].height = graphPtr->bottom - graphPtr->top;
+ rects[2].x = graphPtr->right;
+ rects[2].width = graphPtr->width - graphPtr->right;
+
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, graphPtr->normalBg,
+ rects[0].x, rects[0].y, rects[0].width, rects[0].height,
+ 0, TK_RELIEF_FLAT);
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, graphPtr->normalBg,
+ rects[1].x, rects[1].y, rects[1].width, rects[1].height,
+ 0, TK_RELIEF_FLAT);
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, graphPtr->normalBg,
+ rects[2].x, rects[2].y, rects[2].width, rects[2].height,
+ 0, TK_RELIEF_FLAT);
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, graphPtr->normalBg,
+ rects[3].x, rects[3].y, rects[3].width, rects[3].height,
+ 0, TK_RELIEF_FLAT);
+
+ /* Draw 3D border around the plotting area */
+
+ if (graphPtr->plotBW > 0) {
+ int x, y, w, h;
+
+ x = graphPtr->left - graphPtr->plotBW;
+ y = graphPtr->top - graphPtr->plotBW;
+ w = (graphPtr->right - graphPtr->left) + (2*graphPtr->plotBW);
+ h = (graphPtr->bottom - graphPtr->top) + (2*graphPtr->plotBW);
+ Blt_DrawBackgroundRectangle(graphPtr->tkwin, drawable,
+ graphPtr->normalBg, x, y, w, h, graphPtr->plotBW,
+ graphPtr->plotRelief);
+ }
+ site = Blt_Legend_Site(graphPtr);
+ if (site & LEGEND_MARGIN_MASK) {
+ /* Legend is drawn on one of the graph margins */
+ Blt_DrawLegend(graphPtr, drawable);
+ } else if (site == LEGEND_WINDOW) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ if (graphPtr->title != NULL) {
+ Blt_DrawText(graphPtr->tkwin, drawable, graphPtr->title,
+ &graphPtr->titleTextStyle, graphPtr->titleX, graphPtr->titleY);
+ }
+ Blt_DrawAxes(graphPtr, drawable);
+ graphPtr->flags &= ~DRAW_MARGINS;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DrawPlot --
+ *
+ * Draws the contents of the plotting area. This consists of the
+ * elements, markers (draw under elements), axis limits, and possibly the
+ * legend. Typically, the output will be cached into a backing store
+ * pixmap, so that redraws can occur quickly.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DrawPlot(Graph *graphPtr, Drawable drawable)
+{
+ int site;
+
+ DrawMargins(graphPtr, drawable);
+
+ /* Draw the background of the plotting area with 3D border. */
+ Blt_FillBackgroundRectangle(graphPtr->tkwin, drawable, graphPtr->plotBg,
+ graphPtr->left - graphPtr->plotBW,
+ graphPtr->top - graphPtr->plotBW,
+ graphPtr->right - graphPtr->left + 1 + 2 * graphPtr->plotBW,
+ graphPtr->bottom - graphPtr->top + 1 + 2 * graphPtr->plotBW,
+ graphPtr->plotBW, graphPtr->plotRelief);
+
+ /* Draw the elements, markers, legend, and axis limits. */
+ Blt_DrawAxes(graphPtr, drawable);
+ Blt_DrawGrids(graphPtr, drawable);
+ Blt_DrawMarkers(graphPtr, drawable, MARKER_UNDER);
+
+ site = Blt_Legend_Site(graphPtr);
+ if ((site & LEGEND_PLOTAREA_MASK) && (!Blt_Legend_IsRaised(graphPtr))) {
+ Blt_DrawLegend(graphPtr, drawable);
+ } else if (site == LEGEND_WINDOW) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ Blt_DrawAxisLimits(graphPtr, drawable);
+ Blt_DrawElements(graphPtr, drawable);
+ /* Blt_DrawAxes(graphPtr, drawable); */
+}
+
+void
+Blt_MapGraph(Graph *graphPtr)
+{
+ if (graphPtr->flags & RESET_AXES) {
+ Blt_ResetAxes(graphPtr);
+ }
+ if (graphPtr->flags & LAYOUT_NEEDED) {
+ Blt_LayoutGraph(graphPtr);
+ graphPtr->flags &= ~LAYOUT_NEEDED;
+ }
+ /* Compute coordinate transformations for graph components */
+ if ((graphPtr->vRange > 1) && (graphPtr->hRange > 1)) {
+ if (graphPtr->flags & MAP_WORLD) {
+ Blt_MapAxes(graphPtr);
+ }
+ Blt_MapElements(graphPtr);
+ Blt_MapMarkers(graphPtr);
+ graphPtr->flags &= ~(MAP_ALL);
+ }
+}
+
+void
+Blt_DrawGraph(Graph *graphPtr, Drawable drawable)
+{
+ DrawPlot(graphPtr, drawable);
+ /* Draw markers above elements */
+ Blt_DrawMarkers(graphPtr, drawable, MARKER_ABOVE);
+ Blt_DrawActiveElements(graphPtr, drawable);
+
+ /* Don't draw legend in the plot area. */
+ if ((Blt_Legend_Site(graphPtr) & LEGEND_PLOTAREA_MASK) &&
+ (Blt_Legend_IsRaised(graphPtr))) {
+ Blt_DrawLegend(graphPtr, drawable);
+ }
+ /* Draw 3D border just inside of the focus highlight ring. */
+ if ((graphPtr->borderWidth > 0) && (graphPtr->relief != TK_RELIEF_FLAT)) {
+ Blt_DrawBackgroundRectangle(graphPtr->tkwin, drawable,
+ graphPtr->normalBg, graphPtr->highlightWidth,
+ graphPtr->highlightWidth,
+ graphPtr->width - 2 * graphPtr->highlightWidth,
+ graphPtr->height - 2 * graphPtr->highlightWidth,
+ graphPtr->borderWidth, graphPtr->relief);
+ }
+ /* Draw focus highlight ring. */
+ if ((graphPtr->highlightWidth > 0) && (graphPtr->flags & FOCUS)) {
+ GC gc;
+
+ gc = Tk_GCForColor(graphPtr->highlightColor, drawable);
+ Tk_DrawFocusHighlight(graphPtr->tkwin, gc, graphPtr->highlightWidth,
+ drawable);
+ }
+}
+
+static void
+UpdateMarginTraces(Graph *graphPtr)
+{
+ Margin *marginPtr, *endPtr;
+
+ for (marginPtr = graphPtr->margins, endPtr = marginPtr + 4;
+ marginPtr < endPtr; marginPtr++) {
+ if (marginPtr->varName != NULL) { /* Trigger variable traces */
+ int size;
+
+ if ((marginPtr->site == MARGIN_LEFT) ||
+ (marginPtr->site == MARGIN_RIGHT)) {
+ size = marginPtr->width;
+ } else {
+ size = marginPtr->height;
+ }
+ Tcl_SetVar(graphPtr->interp, marginPtr->varName, Blt_Itoa(size),
+ TCL_GLOBAL_ONLY);
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DisplayGraph --
+ *
+ * This procedure is invoked to display a graph widget.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Commands are output to X to display the graph in its current mode.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DisplayGraph(ClientData clientData)
+{
+ Graph *graphPtr = clientData;
+ Pixmap drawable;
+ Tk_Window tkwin;
+ int site;
+
+ graphPtr->flags &= ~REDRAW_PENDING;
+ if (graphPtr->tkwin == NULL) {
+ return; /* Window has been destroyed (we
+ * should not get here) */
+ }
+ tkwin = graphPtr->tkwin;
+ if ((Tk_Width(tkwin) <= 1) || (Tk_Height(tkwin) <= 1)) {
+ /* Don't bother computing the layout until the size of the window is
+ * something reasonable. */
+ return;
+ }
+ graphPtr->width = Tk_Width(tkwin);
+ graphPtr->height = Tk_Height(tkwin);
+ Blt_MapGraph(graphPtr);
+ if (!Tk_IsMapped(tkwin)) {
+ /* The graph's window isn't displayed, so don't bother drawing
+ * anything. By getting this far, we've at least computed the
+ * coordinates of the graph's new layout. */
+ return;
+ }
+ /* Create a pixmap the size of the window for double buffering. */
+ if (graphPtr->doubleBuffer) {
+ drawable = Tk_GetPixmap(graphPtr->display, Tk_WindowId(tkwin),
+ graphPtr->width, graphPtr->height, Tk_Depth(tkwin));
+ } else {
+ drawable = Tk_WindowId(tkwin);
+ }
+ if (graphPtr->backingStore) {
+ if ((graphPtr->cache == None) ||
+ (graphPtr->cacheWidth != graphPtr->width) ||
+ (graphPtr->cacheHeight != graphPtr->height)) {
+ if (graphPtr->cache != None) {
+ Tk_FreePixmap(graphPtr->display, graphPtr->cache);
+ }
+
+
+ graphPtr->cache = Tk_GetPixmap(graphPtr->display,
+ Tk_WindowId(tkwin), graphPtr->width, graphPtr->height,
+ Tk_Depth(tkwin));
+ graphPtr->cacheWidth = graphPtr->width;
+ graphPtr->cacheHeight = graphPtr->height;
+ graphPtr->flags |= CACHE_DIRTY;
+ }
+ }
+ if (graphPtr->backingStore) {
+ if (graphPtr->flags & CACHE_DIRTY) {
+ /* The backing store is new or out-of-date. */
+ DrawPlot(graphPtr, graphPtr->cache);
+ graphPtr->flags &= ~CACHE_DIRTY;
+ }
+ /* Copy the pixmap to the one used for drawing the entire graph. */
+ XCopyArea(graphPtr->display, graphPtr->cache, drawable,
+ graphPtr->drawGC, 0, 0, Tk_Width(graphPtr->tkwin),
+ Tk_Height(graphPtr->tkwin), 0, 0);
+ } else {
+ DrawPlot(graphPtr, drawable);
+ }
+ /* Draw markers above elements */
+ Blt_DrawMarkers(graphPtr, drawable, MARKER_ABOVE);
+ Blt_DrawActiveElements(graphPtr, drawable);
+ /* Don't draw legend in the plot area. */
+ site = Blt_Legend_Site(graphPtr);
+ if ((site & LEGEND_PLOTAREA_MASK) && (Blt_Legend_IsRaised(graphPtr))) {
+ Blt_DrawLegend(graphPtr, drawable);
+ }
+ if (site == LEGEND_WINDOW) {
+ Blt_Legend_EventuallyRedraw(graphPtr);
+ }
+ /* Draw 3D border just inside of the focus highlight ring. */
+ if ((graphPtr->borderWidth > 0) && (graphPtr->relief != TK_RELIEF_FLAT)) {
+ Blt_DrawBackgroundRectangle(graphPtr->tkwin, drawable,
+ graphPtr->normalBg, graphPtr->highlightWidth,
+ graphPtr->highlightWidth,
+ graphPtr->width - 2 * graphPtr->highlightWidth,
+ graphPtr->height - 2 * graphPtr->highlightWidth,
+ graphPtr->borderWidth, graphPtr->relief);
+ }
+ /* Draw focus highlight ring. */
+ if ((graphPtr->highlightWidth > 0) && (graphPtr->flags & FOCUS)) {
+ GC gc;
+
+ gc = Tk_GCForColor(graphPtr->highlightColor, drawable);
+ Tk_DrawFocusHighlight(graphPtr->tkwin, gc, graphPtr->highlightWidth,
+ drawable);
+ }
+ /* Disable crosshairs before redisplaying to the screen */
+ Blt_DisableCrosshairs(graphPtr);
+ XCopyArea(graphPtr->display, drawable, Tk_WindowId(tkwin),
+ graphPtr->drawGC, 0, 0, graphPtr->width, graphPtr->height, 0, 0);
+ Blt_EnableCrosshairs(graphPtr);
+ if (graphPtr->doubleBuffer) {
+ Tk_FreePixmap(graphPtr->display, drawable);
+ }
+ graphPtr->flags &= ~RESET_WORLD;
+ UpdateMarginTraces(graphPtr);
+}
+
+/*LINTLIBRARY*/
+int
+Blt_GraphCmdInitProc(Tcl_Interp *interp)
+{
+ static Blt_InitCmdSpec cmdSpecs[] = {
+ {"graph", GraphCmd,},
+ {"barchart", BarchartCmd,},
+ };
+ return Blt_InitCmds(interp, "::blt", cmdSpecs, 2);
+}
+
+Graph *
+Blt_GetGraphFromWindowData(Tk_Window tkwin)
+{
+ Graph *graphPtr;
+
+ while (tkwin != NULL) {
+ graphPtr = (Graph *)Blt_GetWindowInstanceData(tkwin);
+ if (graphPtr != NULL) {
+ return graphPtr;
+ }
+ tkwin = Tk_Parent(tkwin);
+ }
+ return NULL;
+}
+
+int
+Blt_GraphType(Graph *graphPtr)
+{
+ switch (graphPtr->classId) {
+ case CID_ELEM_LINE:
+ return GRAPH;
+ case CID_ELEM_BAR:
+ return BARCHART;
+ default:
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ReconfigureGraph --
+ *
+ * Allocates resources for the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ReconfigureGraph(Graph *graphPtr)
+{
+ ConfigureGraph(graphPtr);
+ Blt_ConfigureLegend(graphPtr);
+ Blt_ConfigureElements(graphPtr);
+ Blt_ConfigureAxes(graphPtr);
+ Blt_ConfigureMarkers(graphPtr);
+}
diff --git a/tlt3.0/bltGraph.h b/tlt3.0/bltGraph.h
new file mode 100644
index 0000000..84688cf
--- /dev/null
+++ b/tlt3.0/bltGraph.h
@@ -0,0 +1,698 @@
+
+/*
+ * bltGraph.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_GRAPH_H
+#define _BLT_GRAPH_H
+
+#include "bltInt.h"
+#include "bltWindow.h"
+#include "bltHash.h"
+#include "bltBind.h"
+#include "bltChain.h"
+#include "bltPs.h"
+#include "bltBgStyle.h"
+
+typedef struct _Graph Graph;
+typedef struct _Element Element;
+typedef struct _Legend Legend;
+
+typedef enum {
+ CID_NONE,
+ CID_AXIS_X,
+ CID_AXIS_Y,
+ CID_ELEM_BAR,
+ CID_ELEM_LINE,
+ CID_MARKER_BITMAP,
+ CID_MARKER_IMAGE,
+ CID_MARKER_LINE,
+ CID_MARKER_POLYGON,
+ CID_MARKER_TEXT,
+ CID_MARKER_WINDOW,
+ CID_LEGEND_ENTRY,
+} ClassId;
+
+typedef struct {
+ /* Generic fields common to all graph objects. */
+ ClassId classId; /* Class type of object. */
+ const char *name; /* Identifier to refer the object. */
+ const char *className; /* Class name of object. */
+
+ Graph *graphPtr; /* Graph containing of the object. */
+
+ const char **tags; /* Binding tags for the object. */
+} GraphObj;
+
+#include "bltGrAxis.h"
+#include "bltGrLegd.h"
+
+#define MARKER_UNDER 1 /* Draw markers designated to lie underneath
+ * elements, grids, legend, etc. */
+#define MARKER_ABOVE 0 /* Draw markers designated to rest above
+ * elements, grids, legend, etc. */
+
+#define PADX 2 /* Padding between labels/titles */
+#define PADY 2 /* Padding between labels */
+
+#define MINIMUM_MARGIN 20 /* Minimum margin size */
+
+
+#define BOUND(x, lo, hi) \
+ (((x) > (hi)) ? (hi) : ((x) < (lo)) ? (lo) : (x))
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Graph component structure definitions
+ *
+ *---------------------------------------------------------------------------
+ */
+#define PointInGraph(g,x,y) \
+ (((x) <= (g)->right) && ((x) >= (g)->left) && \
+ ((y) <= (g)->bottom) && ((y) >= (g)->top))
+
+/*
+ * Mask values used to selectively enable GRAPH or BARCHART entries in the
+ * various configuration specs.
+ */
+#define GRAPH (BLT_CONFIG_USER_BIT << 1)
+#define STRIPCHART (BLT_CONFIG_USER_BIT << 2)
+#define BARCHART (BLT_CONFIG_USER_BIT << 3)
+#define LINE_GRAPHS (GRAPH | STRIPCHART)
+#define ALL_GRAPHS (GRAPH | BARCHART | STRIPCHART)
+
+#define ACTIVE_PEN (BLT_CONFIG_USER_BIT << 16)
+#define NORMAL_PEN (BLT_CONFIG_USER_BIT << 17)
+#define ALL_PENS (NORMAL_PEN | ACTIVE_PEN)
+
+typedef struct {
+ Segment2d *segments;
+ int length;
+ int *map;
+} GraphSegments;
+
+typedef struct {
+ Point2d *points;
+ int length;
+ int *map;
+} GraphPoints;
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BarGroup --
+ *
+ * Represents a sets of bars with the same abscissa. This structure is
+ * used to track the display of the bars in the group.
+ *
+ * Each unique abscissa has at least one group. Groups can be
+ * defined by the bar element's -group option. Multiple groups are
+ * needed when you are displaying/comparing similar sets of data (same
+ * abscissas) but belong to a separate group.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ int nSegments; /* Number of occurrences of
+ * x-coordinate */
+ Axis2d axes; /* The axes associated with this
+ * group. (mapped to the x-value) */
+ float sum; /* Sum of the ordinates (y-coorinate) of
+ * each duplicate abscissa. Used to
+ * determine height of stacked bars. */
+ int count; /* Current number of bars seen. Used to
+ * position of the next bar in the
+ * group. */
+ float lastY; /* y-cooridinate position of the
+ * last bar seen. */
+ size_t index; /* Order of group in set (an unique
+ * abscissa may have more than one
+ * group). */
+} BarGroup;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BarSetKey --
+ *
+ * Key for hash table of set of bars. The bar set is defined by
+ * coordinates with the same abscissa (x-coordinate).
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ float value; /* Duplicated abscissa */
+ Axis2d axes; /* Axis mapping of element */
+} BarSetKey;
+
+/*
+ * BarModes --
+ *
+ * Bar elements are displayed according to their x-y coordinates. If two
+ * bars have the same abscissa (x-coordinate), the bar segments will be
+ * drawn according to one of the following modes:
+ */
+
+typedef enum BarModes {
+ BARS_INFRONT, /* Each successive bar in a group is
+ * drawn in front of the previous. */
+ BARS_STACKED, /* Each successive bar in a group is
+ * drawn stacked on top of the previous
+ * bar. */
+ BARS_ALIGNED, /* Each successive bar in a group is
+ * drawn aligned side-by-side to the
+ * previous from right-to-left. */
+ BARS_OVERLAP /* Like "aligned", each successive bar
+ * in a group is drawn from
+ * right-to-left. The bars will overlap
+ * each other by ~50%. */
+} BarMode;
+
+typedef struct _Pen Pen;
+typedef struct _Marker Marker;
+
+typedef Pen *(PenCreateProc)(void);
+typedef int (PenConfigureProc)(Graph *graphPtr, Pen *penPtr);
+typedef void (PenDestroyProc)(Graph *graphPtr, Pen *penPtr);
+
+struct _Pen {
+ const char *name; /* Pen style identifier. If NULL pen
+ * was statically allocated. */
+ ClassId classId; /* Type element using this pen. */
+ const char *typeId; /* String token identifying the type of
+ * pen. */
+ unsigned int flags; /* Indicates if the pen element is
+ * active or normal. */
+ int refCount; /* Reference count for elements using
+ * this pen. */
+ Blt_HashEntry *hashPtr;
+
+ Blt_ConfigSpec *configSpecs; /* Configuration specifications */
+
+ PenConfigureProc *configProc;
+ PenDestroyProc *destroyProc;
+ Graph *graphPtr; /* Graph that the pen is associated
+ * with. */
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Crosshairs
+ *
+ * Contains the line segments positions and graphics context used to
+ * simulate crosshairs (by XOR-ing) on the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct _Crosshairs Crosshairs;
+
+typedef struct {
+ short int width, height; /* Dimensions of the margin */
+ short int axesOffset;
+ short int axesTitleLength; /* Width of the widest title to be
+ * shown. Multiple titles are displayed
+ * in another margin. This is the
+ * minimum space requirement. */
+ short int maxTickWidth;
+ short int maxTickHeight;
+ unsigned int nAxes; /* # of axes to be displayed */
+ Blt_Chain axes; /* Axes associated with this margin */
+ const char *varName; /* If non-NULL, name of variable to be
+ * updated when the margin size
+ * changes */
+ int reqSize; /* Requested size of margin */
+ int site; /* Indicates where margin is located:
+ * left, right, top, or bottom. */
+} Margin;
+
+#define MARGIN_NONE -1
+#define MARGIN_BOTTOM 0 /* x */
+#define MARGIN_LEFT 1 /* y */
+#define MARGIN_TOP 2 /* x2 */
+#define MARGIN_RIGHT 3 /* y2 */
+
+#define rightMargin margins[MARGIN_RIGHT]
+#define leftMargin margins[MARGIN_LEFT]
+#define topMargin margins[MARGIN_TOP]
+#define bottomMargin margins[MARGIN_BOTTOM]
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Graph --
+ *
+ * Top level structure containing everything pertaining to the graph.
+ *
+ *---------------------------------------------------------------------------
+ */
+struct _Graph {
+ unsigned int flags; /* Flags; see below for definitions. */
+ Tcl_Interp *interp; /* Interpreter associated with graph */
+ Tk_Window tkwin; /* Window that embodies the graph.
+ * NULL means that the window has been
+ * destroyed but the data structures
+ * haven't yet been cleaned up. */
+ Display *display; /* Display containing widget; used to
+ * release resources after tkwin has
+ * already gone away. */
+ Tcl_Command cmdToken; /* Token for graph's widget command. */
+ const char *data; /* This value isn't used in C code.
+ * It may be used in TCL bindings to
+ * associate extra data. */
+ Tk_Cursor cursor;
+ int inset; /* Sum of focus highlight and 3-D
+ * border. Indicates how far to
+ * offset the graph from outside edge
+ * of the window. */
+ int borderWidth; /* Width of the exterior border */
+ int relief; /* Relief of the exterior border. */
+ Blt_Background normalBg; /* 3-D border used to delineate the
+ * plot surface and outer edge of
+ * window. */
+ int highlightWidth; /* Width in pixels of highlight to
+ * draw around widget when it has the
+ * focus. <= 0 means don't draw a
+ * highlight. */
+ XColor *highlightBgColor; /* Color for drawing traversal
+ * highlight area when highlight is
+ * off. */
+ XColor *highlightColor; /* Color for drawing traversal
+ * highlight. */
+ const char *title; /* Graph title */
+ short int titleX, titleY; /* Position of title on graph. */
+ short int titleWidth, titleHeight; /* Dimensions of title. */
+ TextStyle titleTextStyle; /* Title attributes: font, color,
+ * etc.*/
+
+ const char *takeFocus; /* Not used in C code, indicates if
+ * widget should be included in focus
+ * traversal. */
+ Axis *focusPtr; /* The axis that currently has focus. */
+
+ int reqWidth, reqHeight; /* Requested size of graph window */
+ int reqPlotWidth, reqPlotHeight; /* Requested size of plot area. Zero
+ * means to adjust the dimension
+ * according to the available space
+ * left in the window. */
+ int width, height; /* Actual size (in pixels) of graph
+ * window or PostScript page. */
+ Blt_HashTable penTable; /* Table of pens */
+ struct Component {
+ Blt_HashTable table; /* Hash table of ids. */
+ Blt_Chain displayList; /* Display list. */
+ Blt_HashTable tagTable; /* Table of bind tags. */
+ } elements, markers, axes;
+
+ Blt_HashTable dataTables; /* Hash table of datatable clients. */
+ ClassId classId; /* Default element type */
+ Blt_BindTable bindTable;
+ int nextMarkerId; /* Tracks next marker identifier
+ * available */
+ Blt_Chain axisChain[4]; /* Chain of axes for each of the
+ * margins. They're separate from the
+ * margin structures to make it easier
+ * to invert the X-Y axes by simply
+ * switching chain pointers. */
+ Margin margins[4];
+ PageSetup *pageSetup; /* Page layout options: see bltGrPS.c */
+ Legend *legend; /* Legend information: see
+ * bltGrLegd.c */
+ Crosshairs *crosshairs; /* Crosshairs information: see
+ * bltGrHairs.c */
+ int halo; /* Maximum distance allowed between
+ * points when searching for a point */
+ int inverted; /* If non-zero, indicates the x and y
+ * axis positions should be inverted. */
+ int stackAxes; /* If non-zero, indicates to stack
+ * mulitple axes in a margin, rather
+ * than layering them one on top of
+ * another. */
+ GC drawGC; /* GC for drawing on the margins. This
+ * includes the axis lines */
+ int plotBW; /* Width of interior 3-D border. */
+ int plotRelief; /* 3-d effect: TK_RELIEF_RAISED etc. */
+ Blt_Background plotBg; /* Color of plotting surface */
+
+ /* If non-zero, force plot to conform to aspect ratio W/H */
+ float aspect;
+
+ short int left, right; /* Coordinates of plot bbox */
+ short int top, bottom;
+
+ Blt_Pad xPad; /* Vertical padding for plotarea */
+ int vRange, vOffset; /* Vertical axis range and offset from
+ * the left side of the graph
+ * window. Used to transform coordinates
+ * to vertical axes. */
+ Blt_Pad yPad; /* Horizontal padding for plotarea */
+ int hRange, hOffset; /* Horizontal axis range and offset from
+ * the top of the graph window. Used to
+ * transform horizontal axes */
+ float vScale, hScale;
+
+ int doubleBuffer; /* If non-zero, draw the graph into a
+ * pixmap first to reduce flashing. */
+ int backingStore; /* If non-zero, cache elements by
+ * drawing them into a pixmap */
+ Pixmap cache; /* Pixmap used to cache elements
+ * displayed. If *backingStore* is
+ * non-zero, each element is drawn into
+ * this pixmap before it is copied onto
+ * the screen. The pixmap then acts as
+ * a cache (only the pixmap is
+ * redisplayed if the none of elements
+ * have changed). This is done so that
+ * markers can be redrawn quickly over
+ * elements without redrawing each
+ * element. */
+ short int cacheWidth, cacheHeight; /* Size of element backing store
+ * pixmap. */
+
+ /*
+ * barchart specific information
+ */
+ float baseline; /* Baseline from bar chart. */
+ float barWidth; /* Default width of each bar in graph
+ * units. The default width is 1.0
+ * units. */
+ BarMode mode; /* Mode describing how to display bars
+ * with the same x-coordinates. Mode can
+ * be "stacked", "aligned", "overlap",
+ * or "infront" */
+ BarGroup *barGroups; /* Contains information about duplicate
+ * x-values in bar elements (malloc-ed).
+ * This information can also be accessed
+ * by the group hash table */
+ int nBarGroups; /* # of entries in barGroups array. If
+ * zero, indicates nothing special
+ * needs to be * done for "stack" or
+ * "align" modes */
+ Blt_HashTable setTable; /* Table managing sets of bars with
+ * the same abscissas. The bars in a
+ * set may be displayed is various
+ * ways: aligned, overlap, infront, or
+ * stacked. */
+ int maxBarSetSize;
+ const char *dataCmd; /* New data callback? */
+
+};
+
+/*
+ * Bit flags definitions:
+ *
+ * All kinds of state information kept here. All these things happen
+ * when the window is available to draw into (DisplayGraph). Need the
+ * window width and height before we can calculate graph layout (i.e. the
+ * screen coordinates of the axes, elements, titles, etc). But we want to
+ * do this only when we have to, not every time the graph is redrawn.
+ *
+ * Same goes for maintaining a pixmap to double buffer graph elements.
+ * Need to mark when the pixmap needs to updated.
+ *
+ *
+ * MAP_ITEM Indicates that the element/marker/axis
+ * configuration has changed such that
+ * its layout of the item (i.e. its
+ * position in the graph window) needs
+ * to be recalculated.
+ *
+ * MAP_ALL Indicates that the layout of the axes and
+ * all elements and markers and the graph need
+ * to be recalculated. Otherwise, the layout
+ * of only those markers and elements that
+ * have changed will be reset.
+ *
+ * GET_AXIS_GEOMETRY Indicates that the size of the axes needs
+ * to be recalculated.
+ *
+ * RESET_AXES Flag to call to Blt_ResetAxes routine.
+ * This routine recalculates the scale offset
+ * (used for mapping coordinates) of each axis.
+ * If an axis limit has changed, then it sets
+ * flags to re-layout and redraw the entire
+ * graph. This needs to happend before the axis
+ * can compute transformations between graph and
+ * screen coordinates.
+ *
+ * LAYOUT_NEEDED
+ *
+ * CACHE_DIRTY If set, redraw all elements into the pixmap
+ * used for buffering elements.
+ *
+ * REDRAW_PENDING Non-zero means a DoWhenIdle handler has
+ * already been queued to redraw this window.
+ *
+ * DRAW_LEGEND Non-zero means redraw the legend. If this is
+ * the only DRAW_* flag, the legend display
+ * routine is called instead of the graph
+ * display routine.
+ *
+ * DRAW_MARGINS Indicates that the margins bordering
+ * the plotting area need to be redrawn.
+ * The possible reasons are:
+ *
+ * 1) an axis configuration changed
+ * 2) an axis limit changed
+ * 3) titles have changed
+ * 4) window was resized.
+ *
+ * GRAPH_FOCUS
+ */
+
+#define HIDE (1<<0) /* 0x0001 */
+#define DELETE_PENDING (1<<1) /* 0x0002 */
+#define REDRAW_PENDING (1<<2) /* 0x0004 */
+#define ACTIVE_PENDING (1<<3) /* 0x0008 */
+#define MAP_ITEM (1<<4) /* 0x0010 */
+#define DIRTY (1<<5) /* 0x0020 */
+#define ACTIVE (1<<6) /* 0x0040 */
+#define FOCUS (1<<7) /* 0x0080 */
+
+#define MAP_ALL (1<<8) /* 0x0100 */
+#define LAYOUT_NEEDED (1<<9) /* 0x0200 */
+#define RESET_AXES (1<<10)/* 0x0400 */
+#define GET_AXIS_GEOMETRY (1<<11)/* 0x0800 */
+
+#define DRAW_LEGEND (1<<12)/* 0x1000 */
+#define DRAW_MARGINS (1<<13)/* 0x2000 */
+#define CACHE_DIRTY (1<<14)/* 0x4000 */
+#define REQ_BACKING_STORE (1<<15)/* 0x8000 */
+#define UNMAP_HIDDEN (1<<16)
+
+#define MAP_WORLD (MAP_ALL|RESET_AXES|GET_AXIS_GEOMETRY)
+#define REDRAW_WORLD (DRAW_LEGEND)
+#define RESET_WORLD (REDRAW_WORLD | MAP_WORLD)
+
+/*
+ * ---------------------- Forward declarations ------------------------
+ */
+
+extern int Blt_CreatePageSetup(Graph *graphPtr);
+
+extern int Blt_CreateCrosshairs(Graph *graphPtr);
+
+extern double Blt_InvHMap(Axis *axisPtr, double x);
+
+extern double Blt_InvVMap(Axis *axisPtr, double x);
+
+extern double Blt_HMap(Axis *axisPtr, double x);
+
+extern double Blt_VMap(Axis *axisPtr, double y);
+
+extern Point2d Blt_InvMap2D(Graph *graphPtr, double x, double y,
+ Axis2d *pairPtr);
+
+extern Point2d Blt_Map2D(Graph *graphPtr, double x, double y,
+ Axis2d *pairPtr);
+
+extern Graph *Blt_GetGraphFromWindowData(Tk_Window tkwin);
+
+extern void Blt_AdjustAxisPointers(Graph *graphPtr);
+
+extern int Blt_PolyRectClip(Region2d *extsPtr, Point2d *inputPts,
+ int nInputPts, Point2d *outputPts);
+
+extern void Blt_ComputeBarStacks(Graph *graphPtr);
+
+extern void Blt_ConfigureCrosshairs(Graph *graphPtr);
+extern void Blt_ConfigureLegend(Graph *graphPtr);
+extern void Blt_ConfigureElements(Graph *graphPtr);
+extern void Blt_ConfigureAxes(Graph *graphPtr);
+extern void Blt_ConfigureMarkers(Graph *graphPtr);
+extern void Blt_ReconfigureGraph(Graph *graphPtr);
+
+extern void Blt_DestroyAxes(Graph *graphPtr);
+
+extern void Blt_DestroyCrosshairs(Graph *graphPtr);
+
+extern void Blt_DestroyElements(Graph *graphPtr);
+
+extern void Blt_DestroyMarkers(Graph *graphPtr);
+
+extern void Blt_DestroyPageSetup(Graph *graphPtr);
+
+extern void Blt_DrawAxes(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_DrawAxisLimits(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_DrawElements(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_DrawActiveElements(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_DrawGraph(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_DrawMarkers(Graph *graphPtr, Drawable drawable, int under);
+
+extern void Blt_Draw2DSegments(Display *display, Drawable drawable, GC gc,
+ Segment2d *segments, int nSegments);
+
+extern int Blt_GetCoordinate(Tcl_Interp *interp, const char *string,
+ double *valuePtr);
+
+extern void Blt_InitBarSetTable(Graph *graphPtr);
+
+extern void Blt_LayoutGraph(Graph *graphPtr);
+
+extern void Blt_EventuallyRedrawGraph(Graph *graphPtr);
+
+extern void Blt_ResetAxes(Graph *graphPtr);
+
+extern void Blt_ResetBarGroups(Graph *graphPtr);
+
+extern void Blt_GraphExtents(Graph *graphPtr, Region2d *extsPtr);
+
+extern void Blt_DisableCrosshairs(Graph *graphPtr);
+
+extern void Blt_EnableCrosshairs(Graph *graphPtr);
+
+extern void Blt_MapGraph(Graph *graphPtr);
+
+extern void Blt_MapAxes(Graph *graphPtr);
+
+extern void Blt_MapElements(Graph *graphPtr);
+
+extern void Blt_MapMarkers(Graph *graphPtr);
+
+extern void Blt_UpdateCrosshairs(Graph *graphPtr);
+
+extern void Blt_DestroyPens(Graph *graphPtr);
+
+extern int Blt_GetPenFromObj(Tcl_Interp *interp, Graph *graphPtr,
+ Tcl_Obj *objPtr, ClassId classId, Pen **penPtrPtr);
+
+extern Pen *Blt_BarPen(const char *penName);
+
+extern Pen *Blt_LinePen(const char *penName);
+
+extern Pen *Blt_CreatePen(Graph *graphPtr, const char *penName,
+ ClassId classId, int objc, Tcl_Obj *const *objv);
+
+extern int Blt_InitLinePens(Graph *graphPtr);
+
+extern int Blt_InitBarPens(Graph *graphPtr);
+
+extern void Blt_FreePen(Pen *penPtr);
+
+extern int Blt_VirtualAxisOp(Graph *graphPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+
+extern int Blt_AxisOp(Tcl_Interp *interp, Graph *graphPtr, int margin,
+ int objc, Tcl_Obj *const *objv);
+
+extern int Blt_ElementOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv, ClassId classId);
+
+extern int Blt_CrosshairsOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+extern int Blt_MarkerOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+extern int Blt_PenOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+extern int Blt_PointInPolygon(Point2d *samplePtr, Point2d *screenPts,
+ int nScreenPts);
+
+extern int Blt_RegionInPolygon(Region2d *extsPtr, Point2d *points,
+ int nPoints, int enclosed);
+
+extern int Blt_PointInSegments(Point2d *samplePtr, Segment2d *segments,
+ int nSegments, double halo);
+
+extern int Blt_PostScriptOp(Graph *graphPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+extern int Blt_GraphUpdateNeeded(Graph *graphPtr);
+
+extern int Blt_DefaultAxes(Graph *graphPtr);
+
+extern Axis *Blt_GetFirstAxis(Blt_Chain chain);
+
+extern void Blt_UpdateAxisBackgrounds(Graph *graphPtr);
+
+extern Marker *Blt_NearestMarker(Graph *graphPtr, int x, int y, int under);
+
+extern Axis *Blt_NearestAxis(Graph *graphPtr, int x, int y);
+
+typedef ClientData (MakeTagProc)(Graph *graphPtr, const char *tagName);
+
+extern MakeTagProc Blt_MakeElementTag;
+extern MakeTagProc Blt_MakeMarkerTag;
+extern MakeTagProc Blt_MakeAxisTag;
+extern Blt_BindTagProc Blt_GraphTags;
+extern Blt_BindTagProc Blt_AxisTags;
+
+extern int Blt_GraphType(Graph *graphPtr);
+
+extern void Blt_UpdateGraph(ClientData clientData);
+
+extern void Blt_GraphSetObjectClass(GraphObj *graphObjPtr,ClassId classId);
+
+extern void Blt_MarkersToPostScript(Graph *graphPtr, Blt_Ps ps, int under);
+extern void Blt_ElementsToPostScript(Graph *graphPtr, Blt_Ps ps);
+extern void Blt_ActiveElementsToPostScript(Graph *graphPtr, Blt_Ps ps);
+extern void Blt_LegendToPostScript(Graph *graphPtr, Blt_Ps ps);
+extern void Blt_AxesToPostScript(Graph *graphPtr, Blt_Ps ps);
+extern void Blt_AxisLimitsToPostScript(Graph *graphPtr, Blt_Ps ps);
+
+extern Element *Blt_LineElement(Graph *graphPtr, const char *name,
+ ClassId classId);
+extern Element *Blt_BarElement(Graph *graphPtr, const char *name,
+ ClassId classId);
+
+extern void Blt_DrawGrids(Graph *graphPtr, Drawable drawable);
+
+extern void Blt_GridsToPostScript(Graph *graphPtr, Blt_Ps ps);
+extern void Blt_InitBarSetTable(Graph *graphPtr);
+extern void Blt_DestroyBarSets(Graph *graphPtr);
+
+/* ---------------------- Global declarations ------------------------ */
+
+extern const char *Blt_GraphClassName(ClassId classId);
+
+#endif /* _BLT_GRAPH_H */
diff --git a/tlt3.0/bltHash.c b/tlt3.0/bltHash.c
new file mode 100644
index 0000000..2d4cf72
--- /dev/null
+++ b/tlt3.0/bltHash.c
@@ -0,0 +1,1266 @@
+
+/*
+ * bltHash.c --
+ *
+ * This module implements an in-memory hash table for the BLT toolkit. Built
+ * upon the TCL hash table, it adds pool allocation 64-bit address handling,
+ * improved array hash function.
+ *
+ * Copyright 2001 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Both the MIX32 and MIX64 routine are from Bob Jenkins.
+ *
+ * Bob Jenkins, 1996. hash.c. Public Domain.
+ * Bob Jenkins, 1997. lookup8.c. Public Domain.
+ *
+ * The hash table implementation is base upon the one in the Tcl distribution.
+ *
+ * Copyright (c) 1991-1993 The Regents of the University of
+ * California.
+ *
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and
+ * redistribution of this file, and for a DISCLAIMER OF ALL
+ * WARRANTIES.
+ *
+ */
+
+#include <bltInt.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "bltHash.h"
+
+/*
+ * When there are this many entries per bucket, on average, rebuild the hash
+ * table to make it larger.
+ */
+
+#define REBUILD_MULTIPLIER 3
+
+/*
+ * Procedure prototypes for static procedures in this file:
+ */
+static Blt_Hash HashArray(const void *key, size_t length);
+static Blt_HashEntry *ArrayFind(Blt_HashTable *tablePtr, const void *key);
+static Blt_HashEntry *ArrayCreate(Blt_HashTable *tablePtr, const void *key,
+ int *isNewPtr);
+static Blt_HashEntry *BogusFind(Blt_HashTable *tablePtr, const void *key);
+static Blt_HashEntry *BogusCreate(Blt_HashTable *tablePtr, const void *key,
+ int *isNewPtr);
+static Blt_Hash HashString(const char *string);
+static void RebuildTable(Blt_HashTable *tablePtr);
+static Blt_HashEntry *StringFind(Blt_HashTable *tablePtr, const void *key);
+static Blt_HashEntry *StringCreate(Blt_HashTable *tablePtr, const void *key,
+ int *isNewPtr);
+static Blt_HashEntry *OneWordFind(Blt_HashTable *tablePtr, const void *key);
+static Blt_HashEntry *OneWordCreate(Blt_HashTable *tablePtr, const void *key,
+ int *isNewPtr);
+
+static Blt_Hash RandomIndex(Blt_HashTable *tablePtr, const void *key);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HashString --
+ *
+ * Compute a one-word summary of a text string, which can be used to
+ * generate a hash index.
+ *
+ * Results:
+ * The return value is a one-word summary of the information in string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_Hash
+HashString(const char *string) /* String from which to compute hash
+ * value. */
+{
+ Blt_Hash result;
+ Blt_Hash c;
+
+ /*
+ * I tried a zillion different hash functions and asked many other
+ * people for advice. Many people had their own favorite functions,
+ * all different, but no-one had much idea why they were good ones.
+ * I chose the one below (multiply by 9 and add new character)
+ * because of the following reasons:
+ *
+ * 1. Multiplying by 10 is perfect for keys that are decimal strings,
+ * and multiplying by 9 is just about as good.
+ * 2. Times-9 is (shift-left-3) plus (old). This means that each
+ * character's bits hang around in the low-order bits of the
+ * hash value for ever, plus they spread fairly rapidly up to
+ * the high-order bits to fill out the hash value. This seems
+ * to work well both for decimal and non-decimal strings.
+ */
+
+ result = 0;
+ while ((c = *string++) != 0) {
+ result += (result << 3) + c;
+ }
+ return (Blt_Hash)result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * StringFind --
+ *
+ * Given a hash table with string keys, and a string key, find the entry
+ * with a matching key.
+ *
+ * Results:
+ * The return value is a token for the matching entry in the hash table,
+ * or NULL if there was no matching entry.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+StringFind(
+ Blt_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const void *key) /* Key to find matching entry. */
+{
+ Blt_Hash hval;
+ Blt_HashEntry *hPtr;
+ size_t hindex;
+
+ hval = HashString((const char *)key);
+ hindex = hval & tablePtr->mask;
+
+ /*
+ * Search all of the entries in the appropriate bucket.
+ */
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL; hPtr = hPtr->nextPtr) {
+ if (hPtr->hval == hval) {
+ const char *p1, *p2;
+
+ for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
+ if (*p1 != *p2) {
+ break;
+ }
+ if (*p1 == '\0') {
+ return hPtr;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * StringCreate --
+ *
+ * Given a hash table with string keys, and a string key, find the entry
+ * with a matching key. If there is no matching entry, then create a new
+ * entry that does match.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry. If this is a
+ * newly-created entry, then *isNewPtr will be set to a non-zero value;
+ * otherwise *isNewPtr will be set to 0. If this is a new entry the
+ * value stored in the entry will initially be 0.
+ *
+ * Side effects:
+ * A new entry may be added to the hash table.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+StringCreate(
+ Blt_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const void *key, /* Key to use to find or create
+ * matching entry. */
+ int *isNewPtr) /* Store info here telling whether a
+ * new entry was created. */
+{
+ Blt_Hash hval;
+ Blt_HashEntry **bucketPtr;
+ Blt_HashEntry *hPtr;
+ size_t size, hindex;
+
+ hval = HashString(key);
+ hindex = hval & tablePtr->mask;
+
+ /* Search all of the entries in this bucket. */
+
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
+ if (hPtr->hval == hval) {
+ const char *p1, *p2;
+
+ for (p1 = key, p2 = hPtr->key.string; ; p1++, p2++) {
+ if (*p1 != *p2) {
+ break;
+ }
+ if (*p1 == '\0') {
+ *isNewPtr = FALSE;
+ return hPtr;
+ }
+ }
+ }
+ }
+
+ /* Entry not found. Add a new one to the bucket. */
+
+ *isNewPtr = TRUE;
+ size = sizeof(Blt_HashEntry) + strlen(key) - sizeof(Blt_HashKey) + 1;
+ if (tablePtr->hPool != NULL) {
+ hPtr = Blt_PoolAllocItem(tablePtr->hPool, size);
+ } else {
+ hPtr = malloc(size);
+ }
+ bucketPtr = tablePtr->buckets + hindex;
+ hPtr->nextPtr = *bucketPtr;
+ hPtr->hval = hval;
+ hPtr->clientData = 0;
+ strcpy(hPtr->key.string, key);
+ *bucketPtr = hPtr;
+ tablePtr->numEntries++;
+
+ /*
+ * If the table has exceeded a decent size, rebuild it with many more
+ * buckets.
+ */
+
+ if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+ RebuildTable(tablePtr);
+ }
+ return hPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HashOneWord --
+ *
+ * Compute a one-word hash value of a 64-bit word, which then can be used
+ * to generate a hash index.
+ *
+ * From Knuth, it's a multiplicative hash. Multiplies an unsigned 64-bit
+ * value with the golden ratio (sqrt(5) - 1) / 2. The downshift value is
+ * 64 - n, where n is the log2 of the size of the hash table.
+ *
+ * Results:
+ * The return value is a one-word summary of the information in 64 bit
+ * word.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_Hash RandomIndex(Blt_HashTable *tablePtr, const void *key)
+{
+ if (sizeof(void*) == 8) {
+ uint64_t a0, a1;
+ uint64_t y0, y1;
+ uint64_t y2, y3;
+ uint64_t p1, p2;
+ uint64_t result;
+ /* Compute key * GOLDEN_RATIO in 128-bit arithmetic */
+ a0 = (uint64_t)key & 0x00000000FFFFFFFF;
+ a1 = (uint64_t)key >> 32;
+
+ y0 = a0 * 0x000000007f4a7c13;
+ y1 = a0 * 0x000000009e3779b9;
+ y2 = a1 * 0x000000007f4a7c13;
+ y3 = a1 * 0x000000009e3779b9;
+ y1 += y0 >> 32; /* Can't carry */
+ y1 += y2; /* Might carry */
+ if (y1 < y2) {
+ y3 += (1LL << 32); /* Propagate */
+ }
+
+ /* 128-bit product: p1 = loword, p2 = hiword */
+ p1 = ((y1 & 0x00000000FFFFFFFF) << 32) + (y0 & 0x00000000FFFFFFFF);
+ p2 = y3 + (y1 >> 32);
+
+ /* Left shift the value downward by the size of the table */
+ if (tablePtr->downShift > 0) {
+ if (tablePtr->downShift < 64) {
+ result = ((p2 << (64 - tablePtr->downShift)) |
+ (p1 >> (tablePtr->downShift & 63)));
+ } else {
+ result = p2 >> (tablePtr->downShift & 63);
+ }
+ } else {
+ result = p1;
+ }
+ /* Finally mask off the high bits */
+ return (Blt_Hash)(result & tablePtr->mask);
+ }
+ else {
+ return (((((long) (key))*1103515245) >> (tablePtr)->downShift) & (tablePtr)->mask);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OneWordFind --
+ *
+ * Given a hash table with one-word keys, and a one-word key, find the
+ * entry with a matching key.
+ *
+ * Results:
+ * The return value is a token for the matching entry in the hash table,
+ * or NULL if there was no matching entry.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+OneWordFind(
+ Blt_HashTable *tablePtr, /* Table where to lookup entry. */
+ const void *key) /* Key that we're searching for. */
+{
+ Blt_HashEntry *hPtr;
+ size_t hindex;
+
+ hindex = RandomIndex(tablePtr, key);
+
+ /* Search all of the entries in the appropriate bucket. */
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
+ if (hPtr->key.oneWordValue == key) {
+ return hPtr;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OneWordCreate --
+ *
+ * Given a hash table with one-word keys, and a one-word key, find the
+ * entry with a matching key. If there is no matching entry, then create
+ * a new entry that does match.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry. If this is a
+ * newly-created entry, then *isNewPtr will be set to a non-zero value;
+ * otherwise *isNewPtr will be set to 0. If this is a new entry the value
+ * stored in the entry will initially be 0.
+ *
+ * Side effects:
+ * A new entry may be added to the hash table.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+OneWordCreate(
+ Blt_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const void *key, /* Key to use to find or create
+ * matching entry. */
+ int *isNewPtr) /* Store info here telling whether a
+ * new entry was created. */
+{
+ Blt_HashEntry **bucketPtr;
+ Blt_HashEntry *hPtr;
+ size_t hindex;
+
+ hindex = RandomIndex(tablePtr, key);
+
+ /* Search all of the entries in this bucket. */
+
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL; hPtr = hPtr->nextPtr) {
+ if (hPtr->key.oneWordValue == key) {
+ *isNewPtr = FALSE;
+ return hPtr;
+ }
+ }
+
+ /* Entry not found. Add a new one to the bucket. */
+
+ *isNewPtr = TRUE;
+ if (tablePtr->hPool != NULL) {
+ hPtr = Blt_PoolAllocItem(tablePtr->hPool, sizeof(Blt_HashEntry));
+ } else {
+ hPtr = malloc(sizeof(Blt_HashEntry));
+ }
+ bucketPtr = tablePtr->buckets + hindex;
+ hPtr->nextPtr = *bucketPtr;
+ hPtr->hval = (Blt_Hash)key;
+ hPtr->clientData = 0;
+ hPtr->key.oneWordValue = (void *)key; /* const XXXX */
+ *bucketPtr = hPtr;
+ tablePtr->numEntries++;
+
+ /*
+ * If the table has exceeded a decent size, rebuild it with many more
+ * buckets.
+ */
+
+ if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+ RebuildTable(tablePtr);
+ }
+ return hPtr;
+}
+
+
+#if (INTPTR_MAX == INT32_MAX)
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MIX32 --
+ *
+ * Bob Jenkins, 1996. Public Domain.
+ *
+ * Mix 3 32/64-bit values reversibly. For every delta with one or two
+ * bit set, and the deltas of all three high bits or all three low bits,
+ * whether the original value of a,b,c is almost all zero or is uniformly
+ * distributed, If mix() is run forward or backward, at least 32 bits in
+ * a,b,c have at least 1/4 probability of changing. * If mix() is run
+ * forward, every bit of c will change between 1/3 and 2/3 of the time.
+ * (Well, 22/100 and 78/100 for some 2-bit deltas.) mix() was built out
+ * of 36 single-cycle latency instructions in a structure that could
+ * supported 2x parallelism, like so:
+ *
+ * a -= b;
+ * a -= c; x = (c>>13);
+ * b -= c; a ^= x;
+ * b -= a; x = (a<<8);
+ * c -= a; b ^= x;
+ * c -= b; x = (b>>13);
+ * ...
+ *
+ * Unfortunately, superscalar Pentiums and Sparcs can't take advantage
+ * of that parallelism. They've also turned some of those single-cycle
+ * latency instructions into multi-cycle latency instructions. Still,
+ * this is the fastest good hash I could find. There were about 2^^68
+ * to choose from. I only looked at a billion or so.
+ *
+ * --------------------------------------------------------------------------
+ */
+#define MIX32(a,b,c) \
+ a -= b, a -= c, a ^= (c >> 13), \
+ b -= c, b -= a, b ^= (a << 8), \
+ c -= a, c -= b, c ^= (b >> 13), \
+ a -= b, a -= c, a ^= (c >> 12), \
+ b -= c, b -= a, b ^= (a << 16), \
+ c -= a, c -= b, c ^= (b >> 5), \
+ a -= b, a -= c, a ^= (c >> 3), \
+ b -= c, b -= a, b ^= (a << 10), \
+ c -= a, c -= b, c ^= (b >> 15)
+
+#define GOLDEN_RATIO32 0x9e3779b9 /* An arbitrary value */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HashArray --
+ *
+ * Bob Jenkins, 1996. Public Domain.
+ *
+ * This works on all machines. Length has to be measured in unsigned
+ * longs instead of bytes. It requires that
+ *
+ * o The key be an array of unsigned ints.
+ * o All your machines have the same endianness
+ * o The length be the number of unsigned ints in the key.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_Hash
+HashArray(const void *key, size_t length)
+{
+ uint32_t a, b, c, len;
+ uint32_t *arrayPtr = (uint32_t *)key;
+ /* Set up the internal state */
+ len = length;
+ a = b = GOLDEN_RATIO32; /* An arbitrary value */
+ c = 0; /* Previous hash value */
+
+ while (len >= 3) { /* Handle most of the key */
+ a += arrayPtr[0];
+ b += arrayPtr[1];
+ c += arrayPtr[2];
+ MIX32(a, b, c);
+ arrayPtr += 3; len -= 3;
+ }
+ c += length;
+ /* And now the last 2 words */
+ /* Note that all the case statements fall through */
+ switch(len) {
+ /* c is reserved for the length */
+ case 2 : b += arrayPtr[1];
+ case 1 : a += arrayPtr[0];
+ /* case 0: nothing left to add */
+ }
+ MIX32(a, b, c);
+ return (Blt_Hash)c;
+}
+#endif
+
+#if (INTPTR_MAX == INT64_MAX)
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MIX64 --
+ *
+ * Bob Jenkins, January 4 1997, Public Domain. You can use this free for
+ * any purpose. It has no warranty.
+ *
+ * Returns a 64-bit value. Every bit of the key affects every bit of the
+ * return value. No funnels. Every 1-bit and 2-bit delta achieves
+ * avalanche. About 41+5len instructions.
+ *
+ * The best hash table sizes are powers of 2. There is no need to do mod
+ * a prime (mod is sooo slow!). If you need less than 64 bits, use a
+ * bitmask. For example, if you need only 10 bits, do h = (h &
+ * hashmask(10)); In which case, the hash table should have hashsize(10)
+ * elements.
+ *
+ * By Bob Jenkins, Jan 4 1997. bob_jenkins at burtleburtle.net. You may
+ * use this code any way you wish, private, educational, or commercial,
+ * as long as this whole comment accompanies it.
+ *
+ * See http://burtleburtle.net/bob/hash/evahash.html Use for hash table
+ * lookup, or anything where one collision in 2^^64 * is acceptable. Do
+ * NOT use for cryptographic purposes.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#define MIX64(a,b,c) \
+ a -= b, a -= c, a ^= (c >> 43), \
+ b -= c, b -= a, b ^= (a << 9), \
+ c -= a, c -= b, c ^= (b >> 8), \
+ a -= b, a -= c, a ^= (c >> 38), \
+ b -= c, b -= a, b ^= (a << 23), \
+ c -= a, c -= b, c ^= (b >> 5), \
+ a -= b, a -= c, a ^= (c >> 35), \
+ b -= c, b -= a, b ^= (a << 49), \
+ c -= a, c -= b, c ^= (b >> 11), \
+ a -= b, a -= c, a ^= (c >> 12), \
+ b -= c, b -= a, b ^= (a << 18), \
+ c -= a, c -= b, c ^= (b >> 22)
+
+#define GOLDEN_RATIO64 0x9e3779b97f4a7c13LL
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * HashArray --
+ *
+ * Bob Jenkins, January 4 1997, Public Domain. You can use this free for
+ * any purpose. It has no warranty.
+ *
+ * This works on all machines. The length has to be measured in 64 bit
+ * words, instead of bytes. It requires that
+ *
+ * o The key be an array of 64 bit words (unsigned longs).
+ * o All your machines have the same endianness.
+ * o The length be the number of 64 bit words in the key.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_Hash
+HashArray(const void *key, size_t length)
+{
+ uint64_t a, b, c, len;
+ uint32_t *ip = (uint32_t *)key;
+
+#ifdef WORDS_BIGENDIAN
+#define PACK(a,b) ((uint64_t)(b) | ((uint64_t)(a) << 32))
+#else
+#define PACK(a,b) ((uint64_t)(a) | ((uint64_t)(b) << 32))
+#endif
+ /* Set up the internal state */
+ len = length; /* Length is the number of 64-bit
+ * words. */
+ a = b = GOLDEN_RATIO64; /* An arbitrary value */
+ c = 0; /* Previous hash value */
+
+ while (len >= 6) { /* Handle most of the key */
+ a += PACK(ip[0], ip[1]);
+ b += PACK(ip[2], ip[3]);
+ c += PACK(ip[4], ip[5]);
+ MIX64(a,b,c);
+ ip += 6; len -= 6;
+ }
+ c += length;
+ /* And now the last 2 words */
+ /* Note that all the case statements fall through */
+ switch(len) {
+ /* c is reserved for the length */
+ case 5 :
+ case 4 :
+ a += PACK(ip[0], ip[1]);
+ b += PACK(ip[2], ip[3]);
+ ip += 4; len -= 4;
+ break;
+ case 3 :
+ case 2 :
+ a += PACK(ip[0], ip[1]);
+ ip += 2; len -= 2;
+ /* case 0: nothing left to add */
+ }
+ if (len > 0) {
+ b += ip[0];
+ }
+ MIX64(a,b,c);
+ return (Blt_Hash)c;
+}
+#endif
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ArrayFind --
+ *
+ * Given a hash table with array-of-int keys, and a key, find the entry
+ * with a matching key.
+ *
+ * Results:
+ * The return value is a token for the matching entry in the hash table,
+ * or NULL if there was no matching entry.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+ArrayFind(
+ Blt_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const void *key) /* Key to use to find matching entry. */
+{
+ Blt_Hash hval;
+ Blt_HashEntry *hPtr;
+ size_t hindex;
+
+ hval = HashArray(key, tablePtr->keyType);
+ hindex = hval & tablePtr->mask;
+
+ /* Search all of the entries in the appropriate bucket. */
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
+ if (hPtr->hval == hval) {
+ uint32_t *ip1, *ip2;
+ size_t count;
+
+ for (ip1 = (uint32_t *)key, ip2 = (uint32_t *)hPtr->key.words,
+ count = tablePtr->keyType; ; count--, ip1++, ip2++) {
+ if (count == 0) {
+ return hPtr;
+ }
+ if (*ip1 != *ip2) {
+ break;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ArrayCreate --
+ *
+ * Given a hash table with one-word keys, and a one-word key, find the
+ * entry with a matching key. If there is no matching entry, then create a
+ * new entry that does match.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry. If this is a
+ * newly-created entry, then *isNewPtr will be set to a non-zero value;
+ * otherwise *isNewPtr will be set to 0. If this is a new entry the value
+ * stored in the entry will initially be 0.
+ *
+ * Side effects:
+ * A new entry may be added to the hash table.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_HashEntry *
+ArrayCreate(
+ Blt_HashTable *tablePtr, /* Table in which to lookup entry. */
+ const void *key, /* Key to use to find or create
+ * matching entry. */
+ int *isNewPtr) /* Store info here telling whether a
+ * new entry was created. */
+{
+ Blt_Hash hval;
+ Blt_HashEntry **bucketPtr;
+ size_t count;
+ Blt_HashEntry *hPtr;
+ uint32_t *ip1, *ip2;
+ size_t size, hindex;
+
+ hval = HashArray(key, tablePtr->keyType);
+ hindex = hval & tablePtr->mask;
+
+ /* Search all of the entries in the appropriate bucket. */
+
+ for (hPtr = tablePtr->buckets[hindex]; hPtr != NULL;
+ hPtr = hPtr->nextPtr) {
+ if (hPtr->hval == hval) {
+ for (ip1 = (uint32_t *)key, ip2 = (uint32_t *)hPtr->key.words,
+ count = tablePtr->keyType; ; count--, ip1++, ip2++) {
+ if (count == 0) {
+ *isNewPtr = FALSE;
+ return hPtr;
+ }
+ if (*ip1 != *ip2) {
+ break;
+ }
+ }
+ }
+ }
+
+ /* Entry not found. Add a new one to the bucket. */
+
+ *isNewPtr = TRUE;
+ /* We assume here that the size of the key is at least 2 words */
+ size = sizeof(Blt_HashEntry) + tablePtr->keyType * sizeof(uint32_t) -
+ sizeof(Blt_HashKey);
+ if (tablePtr->hPool != NULL) {
+ hPtr = Blt_PoolAllocItem(tablePtr->hPool, size);
+ } else {
+ hPtr = malloc(size);
+ }
+ bucketPtr = tablePtr->buckets + hindex;
+ hPtr->nextPtr = *bucketPtr;
+ hPtr->hval = hval;
+ hPtr->clientData = 0;
+ count = tablePtr->keyType;
+ for (ip1 = (uint32_t *)key, ip2 = (uint32_t *)hPtr->key.words;
+ count > 0; count--, ip1++, ip2++) {
+ *ip2 = *ip1;
+ }
+ *bucketPtr = hPtr;
+ tablePtr->numEntries++;
+
+ /*
+ * If the table has exceeded a decent size, rebuild it with many more
+ * buckets.
+ */
+ if (tablePtr->numEntries >= tablePtr->rebuildSize) {
+ RebuildTable(tablePtr);
+ }
+ return hPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BogusFind --
+ *
+ * This procedure is invoked when an Blt_FindHashEntry is called on a
+ * table that has been deleted.
+ *
+ * Results:
+ * If panic returns (which it shouldn't) this procedure returns NULL.
+ *
+ * Side effects:
+ * Generates a panic.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static Blt_HashEntry *
+BogusFind(
+ Blt_HashTable *tablePtr, /* Not used. */
+ const void *key) /* Not used.*/
+{
+ Blt_Panic("called Blt_FindHashEntry on deleted table");
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BogusCreate --
+ *
+ * This procedure is invoked when an Blt_CreateHashEntry is called on a
+ * table that has been deleted.
+ *
+ * Results:
+ * If panic returns (which it shouldn't) this procedure returns NULL.
+ *
+ * Side effects:
+ * Generates a panic.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static Blt_HashEntry *
+BogusCreate(
+ Blt_HashTable *tablePtr, /* Not used. */
+ const void *key, /* Not used. */
+ int *isNewPtr) /* Not used. */
+{
+ Blt_Panic("called Blt_CreateHashEntry on deleted table");
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RebuildTable --
+ *
+ * This procedure is invoked when the ratio of entries to hash buckets
+ * becomes too large. It creates a new table with a larger bucket array
+ * and moves all of the entries into the new table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory gets reallocated and entries get re-hashed to new buckets.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+RebuildTable(Blt_HashTable *tablePtr) /* Table to enlarge. */
+{
+ Blt_HashEntry **oldBuckets;
+ int oldNumBuckets;
+
+ oldBuckets = tablePtr->buckets;
+ oldNumBuckets = tablePtr->numBuckets;
+ /*
+ * Allocate and initialize the new bucket array, and set up hashing
+ * constants for new array size.
+ */
+ tablePtr->numBuckets <<= 2;
+ tablePtr->buckets = calloc(tablePtr->numBuckets, sizeof(Blt_HashEntry *));
+ tablePtr->rebuildSize <<= 2;
+ tablePtr->downShift -= 2;
+ tablePtr->mask = tablePtr->numBuckets - 1;
+
+ /*
+ * Move all of the existing entries into the new bucket array, based on
+ * their hash values.
+ */
+ if (tablePtr->keyType == BLT_ONE_WORD_KEYS) {
+ Blt_HashEntry **hpp, **hend;
+
+ /*
+ * BLT_ONE_WORD_KEYS are handled slightly differently because they use
+ * the current table size (number of buckets) to distribute the entries.
+ */
+ for (hpp = oldBuckets, hend = hpp + oldNumBuckets; hpp < hend; hpp++) {
+ Blt_HashEntry *hPtr, *nextPtr;
+
+ for (hPtr = *hpp; hPtr != NULL; hPtr = nextPtr) {
+ Blt_HashEntry **bucketPtr;
+ size_t hindex;
+
+ nextPtr = hPtr->nextPtr;
+ hindex = RandomIndex(tablePtr, hPtr->key.oneWordValue);
+ bucketPtr = tablePtr->buckets + hindex;
+ hPtr->nextPtr = *bucketPtr;
+ *bucketPtr = hPtr;
+ }
+ }
+ } else {
+ Blt_HashEntry **hpp, **hend;
+
+ for (hpp = oldBuckets, hend = hpp + oldNumBuckets; hpp < hend; hpp++) {
+ Blt_HashEntry *hPtr, *nextPtr;
+
+ for (hPtr = *hpp; hPtr != NULL; hPtr = nextPtr) {
+ Blt_HashEntry **bucketPtr;
+ size_t hindex;
+
+ nextPtr = hPtr->nextPtr;
+ hindex = hPtr->hval & tablePtr->mask;
+ bucketPtr = tablePtr->buckets + hindex;
+ hPtr->nextPtr = *bucketPtr;
+ *bucketPtr = hPtr;
+ }
+ }
+ }
+
+ /*
+ * Free up the old bucket array, if it was dynamically allocated.
+ */
+ if (oldBuckets != tablePtr->staticBuckets) {
+ free(oldBuckets);
+ }
+}
+
+
+/* Public hash table routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitHashTable --
+ *
+ * Given storage for a hash table, set up the fields to prepare the hash
+ * table for use.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TablePtr is now ready to be passed to Blt_FindHashEntry and
+ * Blt_CreateHashEntry.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_InitHashTable(Blt_HashTable *tablePtr, size_t keyType)
+{
+#if (BLT_SMALL_HASH_TABLE != 4)
+ Blt_Panic("Blt_InitHashTable: BLT_SMALL_HASH_TABLE is %d, not 4\n",
+ BLT_SMALL_HASH_TABLE);
+#endif
+ tablePtr->buckets = tablePtr->staticBuckets;
+ tablePtr->numBuckets = BLT_SMALL_HASH_TABLE;
+ tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
+ tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
+ tablePtr->numEntries = 0;
+ tablePtr->rebuildSize = BLT_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
+
+ if (sizeof(void*) == 8)
+ tablePtr->downShift = 62;
+ else
+ tablePtr->downShift = 28;
+
+ /* The number of buckets is always a power of 2, so we can generate the mask
+ * by simply subtracting 1 from the number of buckets. */
+ tablePtr->mask = (Blt_Hash)(tablePtr->numBuckets - 1);
+ tablePtr->keyType = keyType;
+
+ switch (keyType) {
+ case BLT_STRING_KEYS: /* NUL terminated string keys. */
+ tablePtr->findProc = StringFind;
+ tablePtr->createProc = StringCreate;
+ break;
+
+ case BLT_ONE_WORD_KEYS: /* 32 or 64-bit atomic keys. */
+ tablePtr->findProc = OneWordFind;
+ tablePtr->createProc = OneWordCreate;
+ break;
+
+ default: /* Structures/arrays. */
+ if (keyType == 0) {
+ Blt_Panic("Blt_InitHashTable: Key size can't be %d, must be > 0\n",
+ keyType);
+ }
+ tablePtr->findProc = ArrayFind;
+ tablePtr->createProc = ArrayCreate;
+ break;
+ }
+ tablePtr->hPool = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitHashTableWithPool --
+ *
+ * Given storage for a hash table, set up the fields to prepare the hash
+ * table for use. The only difference between this routine and
+ * Blt_InitHashTable is that is uses a pool allocator to allocate memory
+ * for hash table entries. The type of pool is either fixed or variable
+ * size (string) keys.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * TablePtr is now ready to be passed to Blt_FindHashEntry and
+ * Blt_CreateHashEntry.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_InitHashTableWithPool(Blt_HashTable *tablePtr, size_t keyType)
+{
+ Blt_InitHashTable(tablePtr, keyType);
+ if (keyType == BLT_STRING_KEYS) {
+ tablePtr->hPool = Blt_PoolCreate(BLT_VARIABLE_SIZE_ITEMS);
+ } else {
+ tablePtr->hPool = Blt_PoolCreate(BLT_FIXED_SIZE_ITEMS);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DeleteHashEntry --
+ *
+ * Remove a single entry from a hash table.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The entry given by entryPtr is deleted from its table and should never
+ * again be used by the caller. It is up to the caller to free the
+ * clientData field of the entry, if that is relevant.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DeleteHashEntry(Blt_HashTable *tablePtr, Blt_HashEntry *entryPtr)
+{
+ Blt_HashEntry **bucketPtr;
+ size_t hindex;
+
+ if (tablePtr->keyType == BLT_ONE_WORD_KEYS) {
+ hindex = RandomIndex(tablePtr, (const void *)entryPtr->hval);
+ } else {
+ hindex = (entryPtr->hval & tablePtr->mask);
+ }
+ bucketPtr = tablePtr->buckets + hindex;
+ if (*bucketPtr == entryPtr) {
+ *bucketPtr = entryPtr->nextPtr;
+ } else {
+ Blt_HashEntry *prevPtr;
+
+ for (prevPtr = *bucketPtr; /*empty*/; prevPtr = prevPtr->nextPtr) {
+ if (prevPtr == NULL) {
+ Blt_Panic("malformed bucket chain in Blt_DeleteHashEntry");
+ }
+ if (prevPtr->nextPtr == entryPtr) {
+ prevPtr->nextPtr = entryPtr->nextPtr;
+ break;
+ }
+ }
+ }
+ tablePtr->numEntries--;
+ if (tablePtr->hPool != NULL) {
+ Blt_PoolFreeItem(tablePtr->hPool, entryPtr);
+ } else {
+ free(entryPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DeleteHashTable --
+ *
+ * Free up everything associated with a hash table except for the record
+ * for the table itself.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The hash table is no longer useable.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DeleteHashTable(Blt_HashTable *tablePtr) /* Table to delete. */
+{
+ /* Free up all the entries in the table. */
+ if (tablePtr->hPool != NULL) {
+ Blt_PoolDestroy(tablePtr->hPool);
+ tablePtr->hPool = NULL;
+ } else {
+ size_t i;
+
+ for (i = 0; i < tablePtr->numBuckets; i++) {
+ Blt_HashEntry *hPtr;
+
+ hPtr = tablePtr->buckets[i];
+ while (hPtr != NULL) {
+ Blt_HashEntry *nextPtr;
+
+ nextPtr = hPtr->nextPtr;
+ free(hPtr);
+ hPtr = nextPtr;
+ }
+ }
+ }
+
+ /* Free up the bucket array, if it was dynamically allocated. */
+ if (tablePtr->buckets != tablePtr->staticBuckets) {
+ free(tablePtr->buckets);
+ }
+
+ /*
+ * Arrange for panics if the table is used again without re-initialization.
+ */
+ tablePtr->findProc = BogusFind;
+ tablePtr->createProc = BogusCreate;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FirstHashEntry --
+ *
+ * Locate the first entry in a hash table and set up a record that can be
+ * used to step through all the remaining entries of the table.
+ *
+ * Results:
+ * The return value is a pointer to the first entry in tablePtr, or NULL
+ * if tablePtr has no entries in it. The memory at *searchPtr is
+ * initialized so that subsequent calls to Blt_NextHashEntry will return
+ * all of the entries in the table, one at a time.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_HashEntry *
+Blt_FirstHashEntry(
+ Blt_HashTable *tablePtr, /* Table to search. */
+ Blt_HashSearch *searchPtr) /* Place to store information about
+ * progress through the table. */
+{
+ searchPtr->tablePtr = tablePtr;
+ searchPtr->nextIndex = 0;
+ searchPtr->nextEntryPtr = NULL;
+ return Blt_NextHashEntry(searchPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NextHashEntry --
+ *
+ * Once a hash table enumeration has been initiated by calling
+ * Blt_FirstHashEntry, this procedure may be called to return successive
+ * elements of the table.
+ *
+ * Results:
+ * The return value is the next entry in the hash table being enumerated,
+ * or NULL if the end of the table is reached.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_HashEntry *
+Blt_NextHashEntry(Blt_HashSearch *searchPtr)
+{
+ Blt_HashEntry *hPtr;
+
+ while (searchPtr->nextEntryPtr == NULL) {
+ if (searchPtr->nextIndex >= searchPtr->tablePtr->numBuckets) {
+ return NULL;
+ }
+ searchPtr->nextEntryPtr =
+ searchPtr->tablePtr->buckets[searchPtr->nextIndex];
+ searchPtr->nextIndex++;
+ }
+ hPtr = searchPtr->nextEntryPtr;
+ searchPtr->nextEntryPtr = hPtr->nextPtr;
+ return hPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_HashStats --
+ *
+ * Return statistics describing the layout of the hash table in its hash
+ * buckets.
+ *
+ * Results:
+ * The return value is a malloc-ed string containing information about
+ * tablePtr. It is the caller's responsibility to free this string.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_HashStats(Blt_HashTable *tablePtr) /* Table for which to produce stats. */
+{
+ Blt_HashEntry **bp, **bend;
+ char *result, *p;
+ double average, tmp;
+#define NUM_COUNTERS 10
+ size_t count[NUM_COUNTERS], overflow, i, max;
+
+ /* Compute a histogram of bucket usage. */
+ for (i = 0; i < NUM_COUNTERS; i++) {
+ count[i] = 0;
+ }
+ overflow = 0;
+ average = 0.0;
+ max = 0;
+
+ for (bp = tablePtr->buckets, bend = bp + tablePtr->numBuckets; bp < bend;
+ bp++) {
+ Blt_HashEntry *hPtr;
+ size_t j;
+
+ j = 0;
+ for (hPtr = *bp; hPtr != NULL; hPtr = hPtr->nextPtr) {
+ j++;
+ }
+ if (j > max) {
+ max = j;
+ }
+ if (j < NUM_COUNTERS) {
+ count[j]++;
+ } else {
+ overflow++;
+ }
+ tmp = j;
+ average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
+ }
+
+ /* Print out the histogram and a few other pieces of information. */
+ result = malloc((unsigned) ((NUM_COUNTERS*60) + 300));
+ sprintf(result, "%lu entries in table, %lu buckets\n",
+ (unsigned long)tablePtr->numEntries,
+ (unsigned long)tablePtr->numBuckets);
+ p = result + strlen(result);
+ for (i = 0; i < NUM_COUNTERS; i++) {
+ sprintf(p, "number of buckets with %lu entries: %lu\n",
+ (unsigned long)i, (unsigned long)count[i]);
+ p += strlen(p);
+ }
+ sprintf(p, "number of buckets with %d or more entries: %lu\n",
+ NUM_COUNTERS, (unsigned long)overflow);
+ p += strlen(p);
+ sprintf(p, "average search distance for entry: %.2f\n", average);
+ p += strlen(p);
+ sprintf(p, "maximum search distance for entry: %lu", (unsigned long)max);
+ return result;
+}
diff --git a/tlt3.0/bltHash.h b/tlt3.0/bltHash.h
new file mode 100644
index 0000000..dfbf7ce
--- /dev/null
+++ b/tlt3.0/bltHash.h
@@ -0,0 +1,180 @@
+
+/*
+ * bltHash.h --
+ *
+ * Copyright 2000-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The hash table data structures are based upon the ones in the public header
+ * file tcl.h in the Tcl library distribution.
+ *
+ * Copyright (c) 1991-1993 The Regents of the University of California.
+ *
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and
+ * redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifndef BLT_HASH_H
+#define BLT_HASH_H 1
+
+#include <stdint.h>
+
+#if (INTPTR_MAX == INT64_MAX)
+typedef uint64_t Blt_Hash;
+#else
+typedef uint32_t Blt_Hash;
+#endif
+
+#include "bltPool.h"
+
+/*
+ * Acceptable key types for hash tables:
+ */
+#ifndef BLT_STRING_KEYS
+# define BLT_STRING_KEYS 0L
+#endif
+#ifndef BLT_ONE_WORD_KEYS
+# define BLT_ONE_WORD_KEYS ((size_t)-1L)
+#endif
+/*
+ * Forward declaration of Blt_HashTable. Needed by some C++ compilers to
+ * prevent errors when the forward reference to Blt_HashTable is encountered
+ * in the Blt_HashEntry structure.
+ */
+
+#ifdef __cplusplus
+struct Blt_HashTable;
+#endif
+
+typedef union { /* Key has one of these forms: */
+ void *oneWordValue; /* One-word value for key. */
+ unsigned long words[1]; /* Multiple integer words for key. The actual
+ * size will be as large as necessary for this
+ * table's keys. */
+ char string[4]; /* String for key. The actual size will be as
+ * large as needed to hold the key. */
+} Blt_HashKey;
+
+/*
+ * Structure definition for an entry in a hash table. No one outside BLT
+ * should access any of these fields directly; use the macros defined below.
+ */
+typedef struct Blt_HashEntry {
+ struct Blt_HashEntry *nextPtr; /* Pointer to next entry in this hash
+ * bucket, or NULL for end of chain.*/
+ Blt_Hash hval;
+
+ ClientData clientData; /* Application stores something here with
+ * Blt_SetHashValue. */
+ Blt_HashKey key; /* MUST BE LAST FIELD IN RECORD!! */
+} Blt_HashEntry;
+
+/*
+ * Structure definition for a hash table. Must be in blt.h so clients can
+ * allocate space for these structures, but clients should never access any
+ * fields in this structure.
+ */
+#define BLT_SMALL_HASH_TABLE 4
+typedef struct Blt_HashTable {
+ Blt_HashEntry **buckets; /* Pointer to bucket array. Each element
+ * points to first entry in bucket's hash
+ * chain, or NULL. */
+ Blt_HashEntry *staticBuckets[BLT_SMALL_HASH_TABLE];
+ /* Bucket array used for small tables (to
+ * avoid mallocs and frees). */
+ size_t numBuckets; /* Total number of buckets allocated at
+ * buckets. */
+ size_t numEntries; /* Total # of entries present in table. */
+ size_t rebuildSize; /* Enlarge table when numEntries gets to be
+ * this large. */
+ Blt_Hash mask; /* Mask value used in hashing function. */
+ unsigned int downShift; /* Shift count used in hashing function.
+ * Designed to use high- order bits of
+ * randomized keys. */
+ size_t keyType; /* Type of keys used in this table. It's
+ * either BLT_STRING_KEYS, BLT_ONE_WORD_KEYS,
+ * or an integer giving the number of ints
+ * that is the size of the key. */
+ Blt_HashEntry *(*findProc) _ANSI_ARGS_((struct Blt_HashTable *tablePtr,
+ CONST void *key));
+ Blt_HashEntry *(*createProc) _ANSI_ARGS_((struct Blt_HashTable *tablePtr,
+ CONST void *key, int *newPtr));
+
+ Blt_Pool hPool; /* Pointer to the pool allocator used for
+ * entries in this hash table. If NULL, the
+ * standard Tcl_Alloc, Tcl_Free routines will
+ * be used instead. */
+} Blt_HashTable;
+
+/*
+ * Structure definition for information used to keep track of searches through
+ * hash tables:
+ */
+
+typedef struct {
+ Blt_HashTable *tablePtr; /* Table being searched. */
+ unsigned long nextIndex; /* Index of next bucket to be enumerated after
+ * present one. */
+ Blt_HashEntry *nextEntryPtr; /* Next entry to be enumerated in the current
+ * bucket. */
+} Blt_HashSearch;
+
+/*
+ * Macros for clients to use to access fields of hash entries:
+ */
+
+#define Blt_GetHashValue(h) ((h)->clientData)
+#define Blt_SetHashValue(h, value) ((h)->clientData = (ClientData)(value))
+#define Blt_GetHashKey(tablePtr, h) \
+ ((void *) (((tablePtr)->keyType == BLT_ONE_WORD_KEYS) ? \
+ (void *)(h)->key.oneWordValue : (h)->key.string))
+
+/*
+ * Macros to use for clients to use to invoke find and create procedures for
+ * hash tables:
+ */
+#define Blt_FindHashEntry(tablePtr, key) \
+ (*((tablePtr)->findProc))(tablePtr, key)
+#define Blt_CreateHashEntry(tablePtr, key, newPtr) \
+ (*((tablePtr)->createProc))(tablePtr, key, newPtr)
+
+extern void Blt_InitHashTable _ANSI_ARGS_((Blt_HashTable *tablePtr,
+ size_t keyType));
+
+extern void Blt_InitHashTableWithPool _ANSI_ARGS_((Blt_HashTable *tablePtr,
+ size_t keyType));
+
+extern void Blt_DeleteHashTable _ANSI_ARGS_((Blt_HashTable *tablePtr));
+
+extern void Blt_DeleteHashEntry _ANSI_ARGS_((Blt_HashTable *tablePtr,
+ Blt_HashEntry *entryPtr));
+
+extern Blt_HashEntry *Blt_FirstHashEntry _ANSI_ARGS_((
+ Blt_HashTable *tablePtr, Blt_HashSearch *searchPtr));
+
+extern Blt_HashEntry *Blt_NextHashEntry _ANSI_ARGS_((
+ Blt_HashSearch *srchPtr));
+
+extern const char *Blt_HashStats _ANSI_ARGS_((Blt_HashTable *tablePtr));
+
+#endif /* BLT_HASH_H */
diff --git a/tlt3.0/bltImage.c b/tlt3.0/bltImage.c
new file mode 100644
index 0000000..32f14a0
--- /dev/null
+++ b/tlt3.0/bltImage.c
@@ -0,0 +1,156 @@
+
+/*
+ * bltImage.c --
+ *
+ * This module implements image processing procedures for the BLT toolkit.
+ *
+ * Copyright 1997-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Xutil.h>
+
+#include "bltInt.h"
+#include "bltImage.h"
+
+/*
+ * Each call to Tk_GetImage returns a pointer to one of the following
+ * structures, which is used as a token by clients (widgets) that display
+ * images.
+ */
+typedef struct _TkImage {
+ Tk_Window tkwin; /* Window passed to Tk_GetImage (needed
+ * to "re-get" the image later if the *
+ * manager changes). */
+ Display *display; /* Display for tkwin. Needed because
+ * when the image is eventually freed
+ * tkwin may not exist anymore. */
+ struct _TkImageMaster *masterPtr; /* Master for this image (identifiers
+ * image manager, for example). */
+ ClientData instanceData; /* One word argument to pass to image
+ * manager when dealing with this image
+ * instance. */
+ Tk_ImageChangedProc *changeProc; /* Code in widget to call when image
+ * changes in a way that affects
+ * redisplay. */
+ ClientData widgetClientData; /* Argument to pass to changeProc. */
+ struct _TkImage *nextPtr; /* Next in list of all image instances
+ * associated with the same name. */
+} TkImage;
+
+/*
+ * For each image master there is one of the following structures, which
+ * represents a name in the image table and all of the images instantiated from
+ * it. Entries in mainPtr->imageTable point to these structures.
+ */
+typedef struct _TkImageMaster {
+ Tk_ImageType *typePtr; /* Information about image type. NULL
+ * means that no image manager owns this
+ * image: the image was deleted. */
+ ClientData masterData; /* One-word argument to pass to image
+ * mgr when dealing with the master, as
+ * opposed to instances. */
+ int width, height; /* Last known dimensions for image. */
+ void *tablePtr; /* Pointer to hash table containing
+ * image (the imageTable field in some
+ * TkMainInfo structure). */
+ void *hPtr; /* Hash entry in mainPtr->imageTable for
+ * this structure (used to delete the
+ * hash entry). */
+ void *instancePtr; /* Pointer to first in list of instances
+ * derived from this name. */
+ int deleted; /* Flag set when image is being
+ * deleted. */
+ Tk_Window tkwin; /* Main window of interpreter (used to
+ * detect when the world is falling
+ * apart.) */
+} TkImageMaster;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Image_IsDeleted --
+ *
+ * Is there any other way to determine if an image has been deleted?
+ *
+ * Results:
+ * Returns 1 if the image has been deleted, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+int
+Blt_Image_IsDeleted(Tk_Image tkImage) /* Token for image. */
+{
+ TkImage *imagePtr = (TkImage *) tkImage;
+
+ if (imagePtr->masterPtr == NULL) {
+ return TRUE;
+ }
+ return (imagePtr->masterPtr->typePtr == NULL);
+}
+
+/*LINTLIBRARY*/
+Tk_ImageMaster
+Blt_Image_GetMaster(Tk_Image tkImage) /* Token for image. */
+{
+ TkImage *imagePtr = (TkImage *)tkImage;
+
+ return (Tk_ImageMaster)imagePtr->masterPtr;
+}
+
+/*LINTLIBRARY*/
+ClientData
+Blt_Image_GetInstanceData(Tk_Image tkImage) /* Token for image. */
+{
+ TkImage *imagePtr = (TkImage *)tkImage;
+
+ return imagePtr->instanceData;
+}
+
+/*LINTLIBRARY*/
+Tk_ImageType *
+Blt_Image_GetType(Tk_Image tkImage) /* Token for image. */
+{
+ TkImageMaster *masterPtr;
+
+ masterPtr = (TkImageMaster *)Blt_Image_GetMaster(tkImage);
+ return masterPtr->typePtr;
+}
+
+const char *
+Blt_Image_Name(Tk_Image tkImage)
+{
+ Tk_ImageMaster master;
+
+ master = Blt_Image_GetMaster(tkImage);
+ return Tk_NameOfImage(master);
+}
+
+const char *
+Blt_Image_NameOfType(Tk_Image tkImage)
+{
+ TkImageMaster *masterPtr;
+
+ masterPtr = (TkImageMaster *)Blt_Image_GetMaster(tkImage);
+ return masterPtr->typePtr->name;
+}
+
diff --git a/tlt3.0/bltImage.h b/tlt3.0/bltImage.h
new file mode 100644
index 0000000..2dd8eec
--- /dev/null
+++ b/tlt3.0/bltImage.h
@@ -0,0 +1,51 @@
+
+/*
+ * bltImage.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_IMAGE_H
+#define _BLT_IMAGE_H
+
+#define ROTATE_0 0
+#define ROTATE_90 1
+#define ROTATE_180 2
+#define ROTATE_270 3
+
+/* Routines that really should be in the Tk image C API. */
+
+extern int Blt_Image_IsDeleted(Tk_Image tkImage);
+
+extern Tk_ImageMaster Blt_Image_GetMaster(Tk_Image tkImage);
+
+extern Tk_ImageType *Blt_Image_GetType(Tk_Image tkImage);
+
+extern ClientData Blt_Image_GetInstanceData(Tk_Image tkImage);
+
+extern const char *Blt_Image_Name(Tk_Image tkImage);
+extern const char *Blt_Image_NameOfType(Tk_Image tkImage);
+
+#endif /*_BLT_IMAGE_H*/
diff --git a/tlt3.0/bltInit.c b/tlt3.0/bltInit.c
new file mode 100644
index 0000000..036e9e5
--- /dev/null
+++ b/tlt3.0/bltInit.c
@@ -0,0 +1,123 @@
+
+/*
+ * bltInit.c --
+ *
+ * This module initials the BLT toolkit, registering its commands with the
+ * Tcl/Tk interpreter.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitCmd --
+ *
+ * Given the name of a command, return a pointer to the clientData field
+ * of the command.
+ *
+ * Results:
+ * A standard TCL result. If the command is found, TCL_OK is returned
+ * and clientDataPtr points to the clientData field of the command (if
+ * the clientDataPtr in not NULL).
+ *
+ * Side effects:
+ * If the command is found, clientDataPtr is set to the address of the
+ * clientData of the command. If not found, an error message is left
+ * in interp->result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+int
+Blt_InitCmd(Tcl_Interp *interp, const char *nsName, Blt_InitCmdSpec *specPtr)
+{
+ const char *cmdPath;
+ Tcl_DString dString;
+ Tcl_Command cmdToken;
+ Tcl_Namespace *nsPtr;
+
+ Tcl_DStringInit(&dString);
+ if (nsName != NULL) {
+ Tcl_DStringAppend(&dString, nsName, -1);
+ }
+ Tcl_DStringAppend(&dString, "::", -1);
+ Tcl_DStringAppend(&dString, specPtr->name, -1);
+
+ cmdPath = Tcl_DStringValue(&dString);
+ cmdToken = Tcl_FindCommand(interp, cmdPath, (Tcl_Namespace *)NULL, 0);
+ if (cmdToken != NULL) {
+ Tcl_DStringFree(&dString);
+ return TCL_OK; /* Assume command was already initialized */
+ }
+ cmdToken = Tcl_CreateObjCommand(interp, cmdPath, specPtr->cmdProc,
+ specPtr->clientData, specPtr->cmdDeleteProc);
+ Tcl_DStringFree(&dString);
+ nsPtr = Tcl_FindNamespace(interp, nsName, (Tcl_Namespace *)NULL,
+ TCL_LEAVE_ERR_MSG);
+ if (nsPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tcl_Export(interp, nsPtr, specPtr->name, FALSE) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitCmds --
+ *
+ * Given the name of a command, return a pointer to the clientData field
+ * of the command.
+ *
+ * Results:
+ * A standard TCL result. If the command is found, TCL_OK is returned and
+ * clientDataPtr points to the clientData field of the command (if the
+ * clientDataPtr in not NULL).
+ *
+ * Side effects:
+ * If the command is found, clientDataPtr is set to the address of the
+ * clientData of the command. If not found, an error message is left in
+ * interp->result.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_InitCmds(
+ Tcl_Interp *interp,
+ const char *nsName,
+ Blt_InitCmdSpec *specs,
+ int nCmds)
+{
+ Blt_InitCmdSpec *sp, *endPtr;
+
+ for (sp = specs, endPtr = specs + nCmds; sp < endPtr; sp++) {
+ if (Blt_InitCmd(interp, nsName, sp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
diff --git a/tlt3.0/bltInt.c b/tlt3.0/bltInt.c
new file mode 100644
index 0000000..41ad000
--- /dev/null
+++ b/tlt3.0/bltInt.c
@@ -0,0 +1,83 @@
+/*
+ * bltCoreInit.c --
+ *
+ * This module initials the non-Tk command of the BLT toolkit, registering the
+ * commands with the TCL interpreter.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "bltInt.h"
+
+Tcl_AppInitProc Tlt_Init;
+Tcl_AppInitProc Tlt_SafeInit;
+
+int Tlt_Init(Tcl_Interp *interp)
+{
+ Tcl_Namespace *nsPtr;
+
+ if(
+#ifdef USE_TCL_STUBS
+ Tcl_InitStubs(interp, TCL_PATCH_LEVEL, 0)
+#else
+ Tcl_PkgRequire(interp, "Tcl", TCL_PATCH_LEVEL, 0)
+#endif
+ == NULL) {
+ return TCL_ERROR;
+ }
+
+ if(
+#ifdef USE_TK_STUBS
+ Tk_InitStubs(interp, TK_PATCH_LEVEL, 0)
+#else
+ Tcl_PkgRequire(interp, "Tk", TK_PATCH_LEVEL, 0)
+#endif
+ == NULL) {
+ return TCL_ERROR;
+ }
+
+ nsPtr = Tcl_FindNamespace(interp, "::blt", (Tcl_Namespace *)NULL, 0);
+ if (nsPtr == NULL) {
+ nsPtr = Tcl_CreateNamespace(interp, "::blt", NULL, NULL);
+ if (nsPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (Blt_VectorCmdInitProc(interp) != TCL_OK)
+ return TCL_ERROR;
+ if (Blt_GraphCmdInitProc(interp) != TCL_OK)
+ return TCL_ERROR;
+
+ if (Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+int Tlt_SafeInit(Tcl_Interp *interp)
+{
+ return Tlt_Init(interp);
+}
+
+
diff --git a/tlt3.0/bltInt.h b/tlt3.0/bltInt.h
new file mode 100644
index 0000000..8e6cd51
--- /dev/null
+++ b/tlt3.0/bltInt.h
@@ -0,0 +1,331 @@
+/*
+ * bltInt.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_INT_H
+#define _BLT_INT_H
+
+#include <tcl.h>
+#ifdef USE_TCL_STUBS
+#include <tclInt.h>
+#endif
+
+#include <tk.h>
+#ifdef USE_TK_STUBS
+#include <tkInt.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+#include <ctype.h>
+#include <memory.h>
+
+#define TRUE 1
+#define FALSE 0
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_InitCmdSpec --
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ const char *name; /* Name of command */
+ Tcl_ObjCmdProc *cmdProc;
+ Tcl_CmdDeleteProc *cmdDeleteProc;
+ ClientData clientData;
+} Blt_InitCmdSpec;
+
+extern int Blt_DictionaryCompare (const char *s1, const char *s2);
+
+/* ---------------------------------------------------------------- */
+
+#define COUNT_NNEG 0
+#define COUNT_POS 1
+#define COUNT_ANY 2
+
+#define RGB_ANTIQUEWHITE1 "#ffefdb"
+#define RGB_BISQUE1 "#ffe4c4"
+#define RGB_BISQUE2 "#eed5b7"
+#define RGB_BISQUE3 "#cdb79e"
+#define RGB_BLACK "#000000"
+#define RGB_BLUE "#0000ff"
+#define RGB_GREEN "#00ff00"
+#define RGB_GREY "#b0b0b0"
+#define RGB_GREY15 "#262626"
+#define RGB_GREY20 "#333333"
+#define RGB_GREY25 "#404040"
+#define RGB_GREY30 "#4d4d4d"
+#define RGB_GREY35 "#595959"
+#define RGB_GREY40 "#666666"
+#define RGB_GREY50 "#7f7f7f"
+#define RGB_GREY64 "#a3a3a3"
+#define RGB_GREY70 "#b3b3b3"
+#define RGB_GREY75 "#bfbfbf"
+#define RGB_GREY77 "#c3c3c3"
+#define RGB_GREY82 "#d1d1d1"
+#define RGB_GREY85 "#d9d9d9"
+#define RGB_GREY90 "#e5e5e5"
+#define RGB_GREY93 "#ececec"
+#define RGB_GREY95 "#f2f2f2"
+#define RGB_GREY97 "#f7f7f7"
+#define RGB_LIGHTBLUE0 "#e4f7ff"
+#define RGB_LIGHTBLUE00 "#D9F5FF"
+#define RGB_LIGHTBLUE1 "#bfefff"
+#define RGB_LIGHTBLUE2 "#b2dfee"
+#define RGB_LIGHTSKYBLUE1 "#b0e2ff"
+#define RGB_MAROON "#b03060"
+#define RGB_NAVYBLUE "#000080"
+#define RGB_PINK "#ffc0cb"
+#define RGB_BISQUE1 "#ffe4c4"
+#define RGB_RED "#ff0000"
+#define RGB_RED3 "#cd0000"
+#define RGB_WHITE "#ffffff"
+#define RGB_YELLOW "#ffff00"
+#define RGB_SKYBLUE4 "#4a708b"
+
+#define STD_NORMAL_BACKGROUND RGB_GREY85
+#define STD_ACTIVE_BACKGROUND RGB_GREY90
+#define STD_SELECT_BACKGROUND RGB_SKYBLUE4
+#define STD_SELECT_FOREGROUND RGB_WHITE
+
+#define STD_ACTIVE_BG_MONO RGB_BLACK
+#define STD_ACTIVE_FOREGROUND RGB_BLACK
+#define STD_ACTIVE_FG_MONO RGB_WHITE
+#define STD_BORDERWIDTH "2"
+#define STD_FONT_HUGE "{Sans Serif} 18"
+#define STD_FONT_LARGE "{Sans Serif} 14"
+#define STD_FONT_MEDIUM "{Sans Serif} 11"
+#define STD_FONT_NORMAL "{Sans Serif} 9"
+#define STD_FONT_SMALL "{Sans Serif} 8"
+#define STD_FONT_NUMBERS "Math 8"
+#define STD_FONT STD_FONT_NORMAL
+#define STD_INDICATOR_COLOR RGB_RED3
+#define STD_NORMAL_BG_MONO RGB_WHITE
+#define STD_NORMAL_FOREGROUND RGB_BLACK
+#define STD_NORMAL_FG_MONO RGB_BLACK
+#define STD_SELECT_BG_MONO RGB_BLACK
+#define STD_SELECT_BORDERWIDTH "2"
+#define STD_SELECT_FG_MONO RGB_WHITE
+#define STD_SHADOW_MONO RGB_BLACK
+#define STD_SELECT_FONT_HUGE "{Sans Serif} 18 Bold"
+#define STD_SELECT_FONT_LARGE "{Sans Serif} 14 Bold"
+#define STD_SELECT_FONT_MEDIUM "{Sans Serif} 11 Bold"
+#define STD_SELECT_FONT_NORMAL "{Sans Serif} 9 Bold"
+#define STD_SELECT_FONT_SMALL "{Sans Serif} 8 Bold"
+#define STD_SELECT_FONT STD_SELECT_FONT_NORMAL
+#define STD_DISABLED_FOREGROUND RGB_GREY70
+#define STD_DISABLED_BACKGROUND RGB_GREY90
+
+#define LineWidth(w) (((w) > 1) ? (w) : 0)
+
+#ifdef TCL_UTF_MAX
+# define HAVE_UTF 1
+#else
+# define HAVE_UTF 0
+#endif /* TCL_UTF_MAX */
+
+#ifndef TK_RELIEF_SOLID
+# define TK_RELIEF_SOLID TK_RELIEF_FLAT
+#endif
+
+typedef int (QSortCompareProc) (const void *, const void *);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Point2 --
+ *
+ * 2-D coordinate.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ double x, y;
+} Point2d;
+
+typedef struct {
+ float x, y;
+} Point2f;
+
+typedef struct {
+ int x, y;
+} Point2i;
+
+typedef struct {
+ size_t nValues;
+ void *values;
+} Array;
+
+typedef struct {
+ Point2d p, q; /* The two end points of the segment. */
+} Segment2d;
+
+typedef struct {
+ short int width, height;
+} Dim2D;
+
+typedef struct {
+ float left, right, top, bottom;
+} Region2f;
+
+typedef struct {
+ double left, right, top, bottom;
+} Region2d;
+
+#define PointInRegion(e,x,y) \
+ (((x) <= (e)->right) && ((x) >= (e)->left) && \
+ ((y) <= (e)->bottom) && ((y) >= (e)->top))
+
+#define PointInRectangle(r,x0,y0) \
+ (((x0) <= (int)((r)->x + (r)->width - 1)) && ((x0) >= (int)(r)->x) && \
+ ((y0) <= (int)((r)->y + (r)->height - 1)) && ((y0) >= (int)(r)->y))
+
+/*-------------------------------------------------------------------------------
+ *
+ * ColorPair --
+ *
+ * Holds a pair of foreground, background colors.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ XColor *fgColor, *bgColor;
+} ColorPair;
+
+#define COLOR_NONE (XColor *)0
+#define COLOR_DEFAULT (XColor *)1
+#define COLOR_ALLOW_DEFAULTS 1
+
+extern void strtolower(char*);
+
+extern void Blt_FreeColorPair (ColorPair *pairPtr);
+
+extern int Blt_ExprDoubleFromObj (Tcl_Interp *interp, Tcl_Obj *objPtr,
+ double *valuePtr);
+
+extern int Blt_ExprIntFromObj (Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int *valuePtr);
+
+extern const char *Blt_Itoa(int value);
+
+extern const char *Blt_Ltoa(long value);
+
+extern const char *Blt_Utoa(unsigned int value);
+
+extern const char *Blt_Dtoa(Tcl_Interp *interp, double value);
+
+extern int Blt_InitCmd (Tcl_Interp *interp, const char *namespace,
+ Blt_InitCmdSpec *specPtr);
+
+extern int Blt_InitCmds (Tcl_Interp *interp, const char *namespace,
+ Blt_InitCmdSpec *specPtr, int nCmds);
+
+extern int Blt_GlobalEvalObjv(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+extern int Blt_GetDoubleFromString(Tcl_Interp *interp, const char *s,
+ double *valuePtr);
+extern int Blt_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ double *valuePtr);
+
+extern int Blt_LineRectClip(Region2d *regionPtr, Point2d *p, Point2d *q);
+
+extern int Blt_SimplifyLine (Point2d *origPts, int low, int high,
+ double tolerance, int *indices);
+
+extern GC Blt_GetPrivateGC(Tk_Window tkwin, unsigned long gcMask,
+ XGCValues *valuePtr);
+
+extern GC Blt_GetPrivateGCFromDrawable(Display *display, Drawable drawable,
+ unsigned long gcMask, XGCValues *valuePtr);
+
+extern void Blt_FreePrivateGC(Display *display, GC gc);
+
+extern int Blt_GetWindowFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Window *windowPtr);
+
+extern Window Blt_GetParentWindow(Display *display, Window window);
+
+extern int Blt_GetCountFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int check, long *valuePtr);
+
+extern const char *Blt_NameOfFill(int fill);
+
+extern int Blt_GetXY (Tcl_Interp *interp, Tk_Window tkwin,
+ const char *string, int *xPtr, int *yPtr);
+
+extern Point2d Blt_GetProjection (int x, int y, Point2d *p, Point2d *q);
+
+extern Window Blt_GetParent (Display *display, Window tkwin);
+
+extern void Blt_GetBoundingBox (int width, int height, float angle,
+ double *widthPtr, double *heightPtr, Point2d *points);
+
+extern void Blt_TranslateAnchor (int x, int y, int width, int height,
+ Tk_Anchor anchor, int *transXPtr, int *transYPtr);
+
+extern Point2d Blt_AnchorPoint (double x, double y, double width,
+ double height, Tk_Anchor anchor);
+
+extern long Blt_MaxRequestSize (Display *display, size_t elemSize);
+
+extern Window Blt_GetWindowId (Tk_Window tkwin);
+
+extern void Blt_InitXRandrConfig(Tcl_Interp *interp);
+
+extern int Blt_GetWindowRegion(Display *display, Window window, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+
+extern int Blt_AdjustViewport (int offset, int worldSize, int windowSize,
+ int scrollUnits, int scrollMode);
+
+extern void Blt_UpdateScrollbar(Tcl_Interp *interp,
+ Tcl_Obj *scrollCmdObjPtr, int first, int last, int width);
+
+extern GC Blt_GetBitmapGC(Tk_Window tkwin);
+
+#define Tk_RootWindow(tkwin) \
+ RootWindow(Tk_Display(tkwin),Tk_ScreenNumber(tkwin))
+
+#include "bltConfig.h"
+
+extern Tcl_AppInitProc Blt_GraphCmdInitProc;
+extern Tcl_AppInitProc Blt_VectorCmdInitProc;
+
+extern int TclGetLong(Tcl_Interp *interp, const char *s, long *longPtr);
+
+extern int sprintf_s(char *s, size_t size, const char *fmt, /*args*/ ...);
+
+extern void Blt_Panic TCL_VARARGS(const char *, args);
+
+extern void Blt_ScreenDPI(Tk_Window tkwin, unsigned int *xPtr,
+ unsigned int *yPtr);
+
+extern char *Blt_Strdup(const char *string);
+
+#endif /*_BLT_INT_H*/
diff --git a/tlt3.0/bltList.c b/tlt3.0/bltList.c
new file mode 100644
index 0000000..e77b88a
--- /dev/null
+++ b/tlt3.0/bltList.c
@@ -0,0 +1,558 @@
+
+/*
+ * bltList.c --
+ *
+ * The module implements generic linked lists for the BLT toolkit.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "bltInt.h"
+#include "bltList.h"
+
+typedef struct _Blt_ListNode Node;
+typedef struct _Blt_List bltList;
+
+static Node *
+FindString(bltList *listPtr, const char *key)
+{
+ Node *np;
+ char c;
+
+ c = key[0];
+ for (np = listPtr->head; np != NULL; np = np->next) {
+ if ((c == np->key.string[0]) && (strcmp(key, np->key.string) == 0)) {
+ return np;
+ }
+ }
+ return NULL;
+}
+
+static Blt_ListNode
+FindOneWord(bltList *listPtr, const char *key)
+{
+ Node *np;
+
+ for (np = listPtr->head; np != NULL; np = np->next) {
+ if (key == np->key.oneWordValue) {
+ return np;
+ }
+ }
+ return NULL;
+}
+
+static Blt_ListNode
+FindArray(bltList *listPtr, const char *key)
+{
+ Node *np;
+ size_t nBytes;
+
+ nBytes = sizeof(uint32_t) * listPtr->type;
+ for (np = listPtr->head; np != NULL; np = np->next) {
+ if (memcmp(key, np->key.words, nBytes) == 0) {
+ return np;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FreeNode --
+ *
+ * Free the memory allocated for the node.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FreeNode(Blt_ListNode node)
+{
+ free(node);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_Create --
+ *
+ * Creates a new linked list structure and initializes its pointers
+ *
+ * Results:
+ * Returns a pointer to the newly created list structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+Blt_List
+Blt_List_Create(size_t type)
+{
+ bltList *listPtr;
+
+ listPtr = malloc(sizeof(bltList));
+ if (listPtr != NULL) {
+ Blt_List_Init(listPtr, type);
+ }
+ return listPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_CreateNode --
+ *
+ * Creates a list node holder. This routine does not insert the node
+ * into the list, nor does it no attempt to maintain consistency of the
+ * keys. For example, more than one node may use the same key.
+ *
+ * Results:
+ * The return value is the pointer to the newly created node.
+ *
+ * Side Effects:
+ * The key is not copied, only the Uid is kept. It is assumed this key
+ * will not change in the life of the node.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+Blt_ListNode
+Blt_List_CreateNode(bltList *listPtr, const char *key)
+{
+ Node *np;
+ size_t keySize;
+
+ if (listPtr->type == BLT_STRING_KEYS) {
+ keySize = strlen(key) + 1;
+ } else if (listPtr->type == BLT_ONE_WORD_KEYS) {
+ keySize = sizeof(void *);
+ } else {
+ keySize = sizeof(uint32_t) * listPtr->type;
+ }
+ np = calloc(1, sizeof(Node) + keySize - 4);
+ np->clientData = NULL;
+ np->next = np->prev = NULL;
+ np->list = listPtr;
+ switch (listPtr->type) {
+ case BLT_STRING_KEYS:
+ strcpy(np->key.string, key);
+ break;
+ case BLT_ONE_WORD_KEYS:
+ np->key.oneWordValue = key;
+ break;
+ default:
+ memcpy(np->key.words, key, keySize);
+ break;
+ }
+ return np;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_Reset --
+ *
+ * Removes all the entries from a list, removing pointers to the objects
+ * and keys (not the objects or keys themselves). The node counter is
+ * reset to zero.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_Reset(bltList *listPtr) /* List to clear */
+{
+ if (listPtr != NULL) {
+ Node *nextPtr, *np;
+
+ for (np = listPtr->head; np != NULL; np = nextPtr) {
+ nextPtr = np->next;
+ FreeNode(np);
+ }
+ Blt_List_Init(listPtr, listPtr->type);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_Destroy
+ *
+ * Frees the list structure.
+ *
+ * Results:
+ * Returns a pointer to the newly created list structure.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_Destroy(Blt_List list)
+{
+ if (list != NULL) {
+ Blt_List_Reset(list);
+ free(list);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_Init --
+ *
+ * Initializes a linked list.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_Init(bltList *listPtr, size_t type)
+{
+ listPtr->nNodes = 0;
+ listPtr->head = listPtr->tail = NULL;
+ listPtr->type = type;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_LinkAfter --
+ *
+ * Inserts an node following a given node.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_LinkAfter(bltList *listPtr, Node *np, Node *afterPtr)
+{
+ if (listPtr->head == NULL) {
+ listPtr->tail = listPtr->head = np;
+ } else {
+ if (afterPtr == NULL) {
+ /* Prepend to the front of the list */
+ np->next = listPtr->head;
+ np->prev = NULL;
+ listPtr->head->prev = np;
+ listPtr->head = np;
+ } else {
+ np->next = afterPtr->next;
+ np->prev = afterPtr;
+ if (afterPtr == listPtr->tail) {
+ listPtr->tail = np;
+ } else {
+ afterPtr->next->prev = np;
+ }
+ afterPtr->next = np;
+ }
+ }
+ np->list = listPtr;
+ listPtr->nNodes++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_LinkBefore --
+ *
+ * Inserts an node preceding a given node.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_LinkBefore(bltList *listPtr, Node *np, Node *beforePtr)
+{
+ if (listPtr->head == NULL) {
+ listPtr->tail = listPtr->head = np;
+ } else {
+ if (beforePtr == NULL) {
+ /* Append onto the end of the list */
+ np->next = NULL;
+ np->prev = listPtr->tail;
+ listPtr->tail->next = np;
+ listPtr->tail = np;
+ } else {
+ np->prev = beforePtr->prev;
+ np->next = beforePtr;
+ if (beforePtr == listPtr->head) {
+ listPtr->head = np;
+ } else {
+ beforePtr->prev->next = np;
+ }
+ beforePtr->prev = np;
+ }
+ }
+ np->list = listPtr;
+ listPtr->nNodes++;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_UnlinkNode --
+ *
+ * Unlinks an node from the given list. The node itself is not
+ * deallocated, but only removed from the list.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_UnlinkNode(Node *np)
+{
+ bltList *listPtr;
+
+ listPtr = np->list;
+ if (listPtr != NULL) {
+ int unlinked = 0;
+
+ if (listPtr->head == np) {
+ listPtr->head = np->next;
+ unlinked++;
+ }
+ if (listPtr->tail == np) {
+ listPtr->tail = np->prev;
+ unlinked++;
+ }
+ if (np->next != NULL) {
+ np->next->prev = np->prev;
+ unlinked++;
+ }
+ if (np->prev != NULL) {
+ np->prev->next = np->next;
+ unlinked++;
+ }
+ np->list = NULL;
+ if (unlinked) {
+ assert(listPtr->nNodes > 0);
+ listPtr->nNodes--;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_GetNode --
+ *
+ * Find the first node matching the key given.
+ *
+ * Results:
+ * Returns the pointer to the node. If no node matching the key given is
+ * found, then NULL is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*LINTLIBRARY*/
+Blt_ListNode
+Blt_List_GetNode(bltList *listPtr, const char *key)
+{
+ if (listPtr != NULL) {
+ switch (listPtr->type) {
+ case BLT_STRING_KEYS:
+ return FindString(listPtr, key);
+ case BLT_ONE_WORD_KEYS:
+ return FindOneWord(listPtr, key);
+ default:
+ return FindArray(listPtr, key);
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_DeleteNode --
+ *
+ * Unlinks and deletes the given node.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_DeleteNode(Blt_ListNode node)
+{
+ Blt_List_UnlinkNode(node);
+ FreeNode(node);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_DeleteNodeByKey --
+ *
+ * Find the node and free the memory allocated for the node.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_DeleteNodeByKey(Blt_List list, const char *key)
+{
+ Blt_ListNode node;
+
+ node = Blt_List_GetNode(list, key);
+ if (node != NULL) {
+ Blt_List_DeleteNode(node);
+ }
+}
+
+/*LINTLIBRARY*/
+Blt_ListNode
+Blt_List_Append(Blt_List list, const char *key, ClientData clientData)
+{
+ Blt_ListNode node;
+
+ node = Blt_List_CreateNode(list, key);
+ Blt_List_SetValue(node, clientData);
+ Blt_List_AppendNode(list, node);
+ return node;
+}
+
+/*LINTLIBRARY*/
+Blt_ListNode
+Blt_List_Prepend(Blt_List list, const char *key, ClientData clientData)
+{
+ Blt_ListNode node;
+
+ node = Blt_List_CreateNode(list, key);
+ Blt_List_SetValue(node, clientData);
+ Blt_List_PrependNode(list, node);
+ return node;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_GetNthNode --
+ *
+ * Find the node based upon a given position in list.
+ *
+ * Results:
+ * Returns the pointer to the node, if that numbered element
+ * exists. Otherwise NULL.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+Blt_ListNode
+Blt_List_GetNthNode(bltList *listPtr, long position, int direction)
+{
+ if (listPtr == NULL) {
+ return NULL;
+ }
+ if (direction > 0) {
+ Node *np;
+
+ for (np = listPtr->head; np != NULL; np = np->next) {
+ if (position == 0) {
+ return np;
+ }
+ position--;
+ }
+ } else {
+ Node *np;
+
+ for (np = listPtr->tail; np != NULL; np = np->prev) {
+ if (position == 0) {
+ return np;
+ }
+ position--;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_List_Sort --
+ *
+ * Find the node based upon a given position in list.
+ *
+ * Results:
+ * Returns the pointer to the node, if that numbered element
+ * exists. Otherwise NULL.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+void
+Blt_List_Sort(bltList *listPtr, Blt_ListCompareProc *proc)
+{
+ Node **nodes;
+ Node *np;
+ size_t i;
+
+ if (listPtr->nNodes < 2) {
+ return;
+ }
+ nodes = malloc(sizeof(Node *) * (listPtr->nNodes + 1));
+ if (nodes == NULL) {
+ return; /* Out of memory. */
+ }
+ for (i = 0, np = listPtr->head; np != NULL; np = np->next) {
+ nodes[i++] = np;
+ }
+ qsort(nodes, listPtr->nNodes, sizeof(Node *), (QSortCompareProc *)proc);
+
+ /* Rethread the list. */
+ np = nodes[0];
+ listPtr->head = np;
+ np->prev = NULL;
+ for (i = 1; i < listPtr->nNodes; i++) {
+ np->next = nodes[i];
+ np->next->prev = np;
+ np = np->next;
+ }
+ listPtr->tail = np;
+ np->next = NULL;
+ free(nodes);
+}
diff --git a/tlt3.0/bltList.h b/tlt3.0/bltList.h
new file mode 100644
index 0000000..ab53626
--- /dev/null
+++ b/tlt3.0/bltList.h
@@ -0,0 +1,116 @@
+
+/*
+ * bltList.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef _BLT_LIST_H
+#define _BLT_LIST_H
+
+/*
+ * Acceptable key types for hash tables:
+ */
+#ifndef BLT_STRING_KEYS
+#define BLT_STRING_KEYS 0
+#endif
+#ifndef BLT_ONE_WORD_KEYS
+#define BLT_ONE_WORD_KEYS ((size_t)-1)
+#endif
+
+typedef struct _Blt_List *Blt_List;
+typedef struct _Blt_ListNode *Blt_ListNode;
+
+typedef union { /* Key has one of these forms: */
+ const void *oneWordValue; /* One-word value for key. */
+ unsigned int words[1]; /* Multiple integer words for key. The actual
+ * size will be as large as necessary for this
+ * table's keys. */
+ char string[4]; /* String for key. The actual size will be as
+ * large as needed to hold the key. */
+} Blt_ListKey;
+
+/*
+ * A Blt_ListNode is the container structure for the Blt_List.
+ */
+struct _Blt_ListNode {
+ Blt_ListNode prev; /* Link to the previous node */
+ Blt_ListNode next; /* Link to the next node */
+ Blt_List list; /* List to eventually insert node */
+ ClientData clientData; /* Pointer to the data object */
+ Blt_ListKey key; /* MUST BE LAST FIELD IN RECORD!! */
+};
+
+typedef int (Blt_ListCompareProc)(Blt_ListNode *node1Ptr,
+ Blt_ListNode *node2Ptr);
+
+/*
+ * A Blt_List is a doubly chained list structure.
+ */
+struct _Blt_List {
+ Blt_ListNode head; /* Pointer to first element in list */
+ Blt_ListNode tail; /* Pointer to last element in list */
+ size_t nNodes; /* Number of node currently in the list. */
+ size_t type; /* Type of keys in list. */
+};
+
+extern void Blt_List_Init(Blt_List list, size_t type);
+extern void Blt_List_Reset(Blt_List list);
+extern Blt_List Blt_List_Create(size_t type);
+extern void Blt_List_Destroy(Blt_List list);
+extern Blt_ListNode Blt_List_CreateNode(Blt_List list, const char *key);
+extern void Blt_List_DeleteNode(Blt_ListNode node);
+
+extern Blt_ListNode Blt_List_Append(Blt_List list, const char *key,
+ ClientData clientData);
+extern Blt_ListNode Blt_List_Prepend(Blt_List list, const char *key,
+ ClientData clientData);
+extern void Blt_List_LinkAfter(Blt_List list, Blt_ListNode node,
+ Blt_ListNode afterNode);
+extern void Blt_List_LinkBefore(Blt_List list, Blt_ListNode node,
+ Blt_ListNode beforeNode);
+extern void Blt_List_UnlinkNode(Blt_ListNode node);
+extern Blt_ListNode Blt_List_GetNode(Blt_List list, const char *key);
+extern void Blt_List_DeleteNodeByKey(Blt_List list, const char *key);
+extern Blt_ListNode Blt_List_GetNthNode(Blt_List list, long position,
+ int direction);
+extern void Blt_List_Sort(Blt_List list, Blt_ListCompareProc *proc);
+
+#define Blt_List_GetLength(list) \
+ (((list) == NULL) ? 0 : ((struct _Blt_List *)list)->nNodes)
+#define Blt_List_FirstNode(list) \
+ (((list) == NULL) ? NULL : ((struct _Blt_List *)list)->head)
+#define Blt_List_LastNode(list) \
+ (((list) == NULL) ? NULL : ((struct _Blt_List *)list)->tail)
+#define Blt_List_PrevNode(node) ((node)->prev)
+#define Blt_List_NextNode(node) ((node)->next)
+#define Blt_List_GetKey(node) \
+ (((node)->list->type == BLT_STRING_KEYS) \
+ ? (node)->key.string : (node)->key.oneWordValue)
+#define Blt_List_GetValue(node) ((node)->clientData)
+#define Blt_List_SetValue(node, value) \
+ ((node)->clientData = (ClientData)(value))
+#define Blt_List_AppendNode(list, node) \
+ (Blt_List_LinkBefore((list), (node), (Blt_ListNode)NULL))
+#define Blt_List_PrependNode(list, node) \
+ (Blt_List_LinkAfter((list), (node), (Blt_ListNode)NULL))
+
+#endif /* _BLT_LIST_H */
diff --git a/tlt3.0/bltMath.h b/tlt3.0/bltMath.h
new file mode 100644
index 0000000..54814c0
--- /dev/null
+++ b/tlt3.0/bltMath.h
@@ -0,0 +1,45 @@
+
+/*
+ * bltMath.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_MATH_H
+#define _BLT_MATH_H
+
+#include <math.h>
+#include <float.h>
+#include <limits.h>
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+#define MIN3(a,b,c) (((a)<(b))?(((a)<(c))?(a):(c)):(((b)<(c))?(b):(c)))
+#define MAX3(a,b,c) (((a)>(b))?(((a)>(c))?(a):(c)):(((b)>(c))?(b):(c)))
+#define EXP10(x) (pow(10.0,(x)))
+#define ROUND(x) ((int)((x) + (((x)<0.0) ? -0.5 : 0.5)))
+
+#endif /* BLT_MATH_H */
+
diff --git a/tlt3.0/bltNsUtil.c b/tlt3.0/bltNsUtil.c
new file mode 100644
index 0000000..3598e82
--- /dev/null
+++ b/tlt3.0/bltNsUtil.c
@@ -0,0 +1,146 @@
+/*
+ * bltNsUtil.c --
+ *
+ * This module implements utility namespace procedures for the BLT toolkit.
+ *
+ * Copyright 1997-2008 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <tclPort.h>
+#include <tclInt.h>
+
+#include "bltInt.h"
+#include "bltNsUtil.h"
+
+/*ARGSUSED*/
+Tcl_Namespace *
+Blt_GetCommandNamespace(Tcl_Command cmdToken)
+{
+ Command *cmdPtr = (Command *)cmdToken;
+
+ return (Tcl_Namespace *)cmdPtr->nsPtr;
+}
+
+int
+Blt_ParseObjectName(Tcl_Interp *interp, const char *path,
+ Blt_ObjectName *namePtr, unsigned int flags)
+{
+ char *last, *colon;
+
+ namePtr->nsPtr = NULL;
+ namePtr->name = NULL;
+ colon = NULL;
+
+ /* Find the last namespace separator in the qualified name. */
+ last = (char *)(path + strlen(path));
+ while (--last > path) {
+ if ((*last == ':') && (*(last - 1) == ':')) {
+ last++; /* just after the last "::" */
+ colon = last - 2;
+ break;
+ }
+ }
+ if (colon == NULL) {
+ namePtr->name = path;
+ if ((flags & BLT_NO_DEFAULT_NS) == 0) {
+ namePtr->nsPtr = Tcl_GetCurrentNamespace(interp);
+ }
+ return TRUE; /* No namespace designated in name. */
+ }
+
+ /* Separate the namespace and the object name. */
+ *colon = '\0';
+ if (path[0] == '\0') {
+ namePtr->nsPtr = Tcl_GetGlobalNamespace(interp);
+ } else {
+ namePtr->nsPtr = Tcl_FindNamespace(interp, (char *)path, NULL,
+ (flags & BLT_NO_ERROR_MSG) ? 0 : TCL_LEAVE_ERR_MSG);
+ }
+ /* Repair the string. */ *colon = ':';
+
+ if (namePtr->nsPtr == NULL) {
+ return FALSE; /* Namespace doesn't exist. */
+ }
+ namePtr->name =last;
+ return TRUE;
+}
+
+char *
+Blt_MakeQualifiedName(Blt_ObjectName *namePtr, Tcl_DString *resultPtr)
+{
+ Tcl_DStringInit(resultPtr);
+ if ((namePtr->nsPtr->fullName[0] != ':') ||
+ (namePtr->nsPtr->fullName[1] != ':') ||
+ (namePtr->nsPtr->fullName[2] != '\0')) {
+ Tcl_DStringAppend(resultPtr, namePtr->nsPtr->fullName, -1);
+ }
+ Tcl_DStringAppend(resultPtr, "::", -1);
+ Tcl_DStringAppend(resultPtr, (char *)namePtr->name, -1);
+ return Tcl_DStringValue(resultPtr);
+}
+
+static Tcl_Namespace* NamespaceOfVariable(Var *varPtr)
+{
+ if (varPtr->flags & VAR_IN_HASHTABLE) {
+ VarInHash *vhashPtr = (VarInHash *)varPtr;
+ TclVarHashTable *vtablePtr;
+
+ vtablePtr = (TclVarHashTable *)vhashPtr->entry.tablePtr;
+ return (Tcl_Namespace*)(vtablePtr->nsPtr);
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetVariableNamespace --
+ *
+ * Returns the namespace context of the variable. If NULL, this
+ * indicates that the variable is local to the call frame.
+ *
+ * Results:
+ * Returns the context of the namespace in an opaque type.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tcl_Namespace *
+Blt_GetVariableNamespace(Tcl_Interp *interp, const char *path)
+{
+ Blt_ObjectName objName;
+
+ if (!Blt_ParseObjectName(interp, path, &objName, BLT_NO_DEFAULT_NS)) {
+ return NULL;
+ }
+ if (objName.nsPtr == NULL) {
+ Var *varPtr;
+
+ varPtr = (Var *)Tcl_FindNamespaceVar(interp, (char *)path,
+ (Tcl_Namespace *)NULL,
+ TCL_GLOBAL_ONLY);
+ if (varPtr != NULL) {
+ return NamespaceOfVariable(varPtr);
+ }
+ }
+ return objName.nsPtr;
+}
diff --git a/tlt3.0/bltNsUtil.h b/tlt3.0/bltNsUtil.h
new file mode 100644
index 0000000..63f8ae3
--- /dev/null
+++ b/tlt3.0/bltNsUtil.h
@@ -0,0 +1,59 @@
+/*
+ * bltNsUtil.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef BLT_NS_UTIL_H
+#define BLT_NS_UTIL_H 1
+
+#define NS_SEARCH_NONE (0)
+#define NS_SEARCH_CURRENT (1<<0)
+#define NS_SEARCH_GLOBAL (1<<1)
+#define NS_SEARCH_BOTH (NS_SEARCH_GLOBAL | NS_SEARCH_CURRENT)
+
+typedef struct {
+ const char *name;
+ Tcl_Namespace *nsPtr;
+} Blt_ObjectName;
+
+#define BLT_NO_DEFAULT_NS (1<<0)
+#define BLT_NO_ERROR_MSG (1<<1)
+
+/*
+ * Auxillary procedures
+ */
+extern Tcl_Namespace *Blt_GetVariableNamespace(Tcl_Interp *interp,
+ const char *varName);
+
+extern Tcl_Namespace *Blt_GetCommandNamespace(Tcl_Command cmdToken);
+
+extern int Blt_ParseObjectName(Tcl_Interp *interp, const char *name,
+ Blt_ObjectName *objNamePtr, unsigned int flags);
+
+extern char *Blt_MakeQualifiedName(Blt_ObjectName *objNamePtr,
+ Tcl_DString *resultPtr);
+
+#endif /* BLT_NS_UTIL_H */
diff --git a/tlt3.0/bltOp.h b/tlt3.0/bltOp.h
new file mode 100644
index 0000000..ef4c712
--- /dev/null
+++ b/tlt3.0/bltOp.h
@@ -0,0 +1,37 @@
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_OpSpec --
+ *
+ * Structure to specify a set of operations for a TCL command.
+ * This is passed to the Blt_GetOp procedure to look
+ * for a function pointer associated with the operation name.
+ *
+ *---------------------------------------------------------------------------
+ */
+typedef struct {
+ const char *name; /* Name of operation */
+ int minChars; /* Minimum # characters to disambiguate */
+ void *proc;
+ int minArgs; /* Minimum # args required */
+ int maxArgs; /* Maximum # args required */
+ const char *usage; /* Usage message */
+} Blt_OpSpec;
+
+typedef enum {
+ BLT_OP_ARG0, /* Op is the first argument. */
+ BLT_OP_ARG1, /* Op is the second argument. */
+ BLT_OP_ARG2, /* Op is the third argument. */
+ BLT_OP_ARG3, /* Op is the fourth argument. */
+ BLT_OP_ARG4 /* Op is the fifth argument. */
+
+} Blt_OpIndex;
+
+#define BLT_OP_BINARY_SEARCH 0
+#define BLT_OP_LINEAR_SEARCH 1
+
+extern void *Blt_GetOpFromObj(Tcl_Interp *interp, int nSpecs,
+ Blt_OpSpec *specs, int operPos, int objc, Tcl_Obj *const *objv,
+ int flags);
+
diff --git a/tlt3.0/bltParse.c b/tlt3.0/bltParse.c
new file mode 100644
index 0000000..7c188e2
--- /dev/null
+++ b/tlt3.0/bltParse.c
@@ -0,0 +1,511 @@
+/*
+ * bltParse.c --
+ *
+ * Contains a collection of procedures that are used to parse Tcl
+ * commands or parts of commands (like quoted strings or nested
+ * sub-commands).
+ *
+ * This file is copied from tclParse.c in the TCL library distribution.
+ *
+ * Copyright (c) 1987-1993 The Regents of the University of
+ * California.
+ *
+ * Copyright (c) 1994-1998 Sun Microsystems, Inc.
+ *
+ */
+
+/*
+ * Since TCL 8.1.0 these routines have been replaced by ones that
+ * generate byte-codes. But since these routines are used in vector
+ * expressions, where no such byte-compilation is necessary, I now
+ * include them. In fact, the byte-compiled versions would be slower
+ * since the compiled code typically runs only one time.
+ */
+
+#include "bltInt.h"
+#include "bltParse.h"
+
+/*
+ * A table used to classify input characters to assist in parsing
+ * TCL commands. The table should be indexed with a signed character
+ * using the CHAR_TYPE macro. The character may have a negative
+ * value. The CHAR_TYPE macro takes a pointer to a signed character
+ * and a pointer to the last character in the source string. If the
+ * src pointer is pointing at the terminating null of the string,
+ * CHAR_TYPE returns TCL_COMMAND_END.
+ */
+
+#define STATIC_STRING_SPACE 150
+#define TCL_NORMAL 0x01
+#define TCL_SPACE 0x02
+#define TCL_COMMAND_END 0x04
+#define TCL_QUOTE 0x08
+#define TCL_OPEN_BRACKET 0x10
+#define TCL_OPEN_BRACE 0x20
+#define TCL_CLOSE_BRACE 0x40
+#define TCL_BACKSLASH 0x80
+#define TCL_DOLLAR 0x00
+
+/*
+ * The following table assigns a type to each character. Only types
+ * meaningful to TCL parsing are represented here. The table is
+ * designed to be referenced with either signed or unsigned characters,
+ * so it has 384 entries. The first 128 entries correspond to negative
+ * character values, the next 256 correspond to positive character
+ * values. The last 128 entries are identical to the first 128. The
+ * table is always indexed with a 128-byte offset (the 128th entry
+ * corresponds to a 0 character value).
+ */
+
+static unsigned char tclTypeTable[] =
+{
+ /*
+ * Negative character values, from -128 to -1:
+ */
+
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+
+ /*
+ * Positive character values, from 0-127:
+ */
+
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_SPACE, TCL_COMMAND_END, TCL_SPACE,
+ TCL_SPACE, TCL_SPACE, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_SPACE, TCL_NORMAL, TCL_QUOTE, TCL_NORMAL,
+ TCL_DOLLAR, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_COMMAND_END,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACKET,
+ TCL_BACKSLASH, TCL_COMMAND_END, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_OPEN_BRACE,
+ TCL_NORMAL, TCL_CLOSE_BRACE, TCL_NORMAL, TCL_NORMAL,
+
+ /*
+ * Large unsigned character values, from 128-255:
+ */
+
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+ TCL_NORMAL, TCL_NORMAL, TCL_NORMAL, TCL_NORMAL,
+};
+
+#define CHAR_TYPE(src,last) \
+ (((src)==(last))?TCL_COMMAND_END:(tclTypeTable+128)[(int)*(src)])
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ParseNestedCmd --
+ *
+ * This procedure parses a nested TCL command between
+ * brackets, returning the result of the command.
+ *
+ * Results:
+ * The return value is a standard TCL result, which is
+ * TCL_OK unless there was an error while executing the
+ * nested command. If an error occurs then interp->result
+ * contains a standard error message. *TermPtr is filled
+ * in with the address of the character just after the
+ * last one processed; this is usually the character just
+ * after the matching close-bracket, or the null character
+ * at the end of the string if the close-bracket was missing
+ * (a missing close bracket is an error). The result returned
+ * by the command is stored in standard fashion in *parsePtr,
+ * null-terminated, with parsePtr->next pointing to the null
+ * character.
+ *
+ * Side effects:
+ * The storage space at *parsePtr may be expanded.
+ *
+ *---------------------------------------------------------------------------
+ */
+int Blt_ParseNestedCmd(
+ Tcl_Interp *interp, /* Interpreter to use for nested command
+ * evaluations and error messages. */
+ const char *string, /* Character just after opening bracket. */
+ int flags, /* Flags to pass to nested Tcl_Eval. */
+ const char **termPtr, /* Store address of terminating character
+ * here. */
+ ParseValue *parsePtr) /* Information about where to place
+ * result of command. */
+{
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ParseBraces --
+ *
+ * This procedure scans the information between matching
+ * curly braces.
+ *
+ * Results:
+ * The return value is a standard TCL result, which is
+ * TCL_OK unless there was an error while parsing string.
+ * If an error occurs then interp->result contains a
+ * standard error message. *TermPtr is filled
+ * in with the address of the character just after the
+ * last one successfully processed; this is usually the
+ * character just after the matching close-brace. The
+ * information between curly braces is stored in standard
+ * fashion in *parsePtr, null-terminated with parsePtr->next
+ * pointing to the terminating null character.
+ *
+ * Side effects:
+ * The storage space at *parsePtr may be expanded.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int Blt_ParseBraces(
+ Tcl_Interp *interp, /* Interpreter to use for nested command
+ * evaluations and error messages. */
+ const char *string, /* Character just after opening bracket. */
+ const char **termPtr, /* Store address of terminating character
+ * here. */
+ ParseValue *parsePtr) /* Information about where to place
+ * result of command. */
+{
+ int level;
+ const char *src;
+ char *dest, *end;
+ char c;
+ const char *lastChar = string + strlen(string);
+
+ src = string;
+ dest = parsePtr->next;
+ end = parsePtr->end;
+ level = 1;
+
+ /*
+ * Copy the characters one at a time to the result area, stopping
+ * when the matching close-brace is found.
+ */
+
+ for (;;) {
+ c = *src;
+ src++;
+
+ if (dest == end) {
+ parsePtr->next = dest;
+ (*parsePtr->expandProc) (parsePtr, 20);
+ dest = parsePtr->next;
+ end = parsePtr->end;
+ }
+ *dest = c;
+ dest++;
+
+ if (CHAR_TYPE(src - 1, lastChar) == TCL_NORMAL) {
+ continue;
+ } else if (c == '{') {
+ level++;
+ } else if (c == '}') {
+ level--;
+ if (level == 0) {
+ dest--; /* Don't copy the last close brace. */
+ break;
+ }
+ } else if (c == '\\') {
+ int count;
+
+ /*
+ * Must always squish out backslash-newlines, even when in
+ * braces. This is needed so that this sequence can appear
+ * anywhere in a command, such as the middle of an expression.
+ */
+
+ if (*src == '\n') {
+ dest[-1] = Tcl_Backslash(src - 1, &count);
+ src += count - 1;
+ } else {
+ Tcl_Backslash(src - 1, &count);
+ while (count > 1) {
+ if (dest == end) {
+ parsePtr->next = dest;
+ (*parsePtr->expandProc) (parsePtr, 20);
+ dest = parsePtr->next;
+ end = parsePtr->end;
+ }
+ *dest = *src;
+ dest++;
+ src++;
+ count--;
+ }
+ }
+ } else if (c == '\0') {
+ Tcl_AppendResult(interp, "missing close-brace", (char *)NULL);
+ *termPtr = string - 1;
+ return TCL_ERROR;
+ }
+ }
+
+ *dest = '\0';
+ parsePtr->next = dest;
+ *termPtr = src;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ExpandParseValue --
+ *
+ * This procedure is commonly used as the value of the
+ * expandProc in a ParseValue. It uses malloc to allocate
+ * more space for the result of a parse.
+ *
+ * Results:
+ * The buffer space in *parsePtr is reallocated to something
+ * larger, and if parsePtr->clientData is non-zero the old
+ * buffer is freed. Information is copied from the old
+ * buffer to the new one.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void Blt_ExpandParseValue(
+ ParseValue *parsePtr, /* Information about buffer that
+ * must be expanded. If the clientData
+ * in the structure is non-zero, it
+ * means that the current buffer is
+ * dynamically allocated. */
+ int needed) /* Minimum amount of additional space
+ * to allocate. */
+{
+ int size;
+ char *buffer;
+
+ /*
+ * Either double the size of the buffer or add enough new space
+ * to meet the demand, whichever produces a larger new buffer.
+ */
+ size = (parsePtr->end - parsePtr->buffer) + 1;
+ if (size < needed) {
+ size += needed;
+ } else {
+ size += size;
+ }
+ buffer = malloc((unsigned int)size);
+
+ /*
+ * Copy from old buffer to new, free old buffer if needed, and
+ * mark new buffer as malloc-ed.
+ */
+ memcpy((VOID *) buffer, (VOID *) parsePtr->buffer,
+ (size_t) (parsePtr->next - parsePtr->buffer));
+ parsePtr->next = buffer + (parsePtr->next - parsePtr->buffer);
+ if (parsePtr->clientData != 0) {
+ free(parsePtr->buffer);
+ }
+ parsePtr->buffer = buffer;
+ parsePtr->end = buffer + size - 1;
+ parsePtr->clientData = (ClientData)1;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ParseQuotes --
+ *
+ * This procedure parses a double-quoted string such as a
+ * quoted TCL command argument or a quoted value in a Tcl
+ * expression. This procedure is also used to parse array
+ * element names within parentheses, or anything else that
+ * needs all the substitutions that happen in quotes.
+ *
+ * Results:
+ * The return value is a standard TCL result, which is
+ * TCL_OK unless there was an error while parsing the
+ * quoted string. If an error occurs then interp->result
+ * contains a standard error message. *TermPtr is filled
+ * in with the address of the character just after the
+ * last one successfully processed; this is usually the
+ * character just after the matching close-quote. The
+ * fully-substituted contents of the quotes are stored in
+ * standard fashion in *parsePtr, null-terminated with
+ * parsePtr->next pointing to the terminating null character.
+ *
+ * Side effects:
+ * The buffer space in parsePtr may be enlarged by calling its
+ * expandProc.
+ *
+ *---------------------------------------------------------------------------
+ */
+int Blt_ParseQuotes(
+ Tcl_Interp *interp, /* Interpreter to use for nested command
+ * evaluations and error messages. */
+ const char *string, /* Character just after opening double-
+ * quote. */
+ int termChar, /* Character that terminates "quoted" string
+ * (usually double-quote, but sometimes
+ * right-paren or something else). */
+ int flags, /* Flags to pass to nested Tcl_Eval calls. */
+ const char **termPtr, /* Store address of terminating character
+ * here. */
+ ParseValue *parsePtr) /* Information about where to place
+ * fully-substituted result of parse. */
+{
+ const char *src;
+ char *dest, c;
+ const char *lastChar = string + strlen(string);
+
+ src = string;
+ dest = parsePtr->next;
+
+ for (;;) {
+ if (dest == parsePtr->end) {
+ /*
+ * Target buffer space is about to run out. Make more space.
+ */
+ parsePtr->next = dest;
+ (*parsePtr->expandProc) (parsePtr, 1);
+ dest = parsePtr->next;
+ }
+ c = *src;
+ src++;
+ if (c == termChar) {
+ *dest = '\0';
+ parsePtr->next = dest;
+ *termPtr = src;
+ return TCL_OK;
+ } else if (CHAR_TYPE(src - 1, lastChar) == TCL_NORMAL) {
+ copy:
+ *dest = c;
+ dest++;
+ continue;
+ } else if (c == '$') {
+ int length;
+ const char *value;
+
+ value = Tcl_ParseVar(interp, src - 1, termPtr);
+ if (value == NULL) {
+ return TCL_ERROR;
+ }
+ src = *termPtr;
+ length = strlen(value);
+ if ((parsePtr->end - dest) <= length) {
+ parsePtr->next = dest;
+ (*parsePtr->expandProc) (parsePtr, length);
+ dest = parsePtr->next;
+ }
+ strcpy(dest, value);
+ dest += length;
+ continue;
+ } else if (c == '[') {
+ int result;
+
+ parsePtr->next = dest;
+ result = Blt_ParseNestedCmd(interp, src, flags, termPtr, parsePtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ src = *termPtr;
+ dest = parsePtr->next;
+ continue;
+ } else if (c == '\\') {
+ int nRead;
+
+ src--;
+ *dest = Tcl_Backslash(src, &nRead);
+ dest++;
+ src += nRead;
+ continue;
+ } else if (c == '\0') {
+ char buf[10];
+
+ Tcl_ResetResult(interp);
+ sprintf_s(buf, 10, "missing %c", termChar);
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), buf, 9);
+ *termPtr = string - 1;
+ return TCL_ERROR;
+ } else {
+ goto copy;
+ }
+ }
+}
+
diff --git a/tlt3.0/bltParse.h b/tlt3.0/bltParse.h
new file mode 100644
index 0000000..c56f3d6
--- /dev/null
+++ b/tlt3.0/bltParse.h
@@ -0,0 +1,47 @@
+
+/*
+ * bltParse.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_PARSE_H
+#define _BLT_PARSE_H
+
+typedef struct _ParseValue ParseValue;
+struct _ParseValue {
+ char *buffer;
+ char *next;
+ char *end;
+ void (*expandProc)(ParseValue *pvPtr, int needed);
+ ClientData clientData;
+};
+
+extern int Blt_ParseBraces(Tcl_Interp *interp, const char *string,
+ const char **termPtr, ParseValue *pvPtr);
+extern int Blt_ParseNestedCmd(Tcl_Interp *interp, const char *string,
+ int flags, const char **termPtr, ParseValue *pvPtr);
+extern int Blt_ParseQuotes(Tcl_Interp *interp, const char *string,
+ int termChar, int flags, const char **termPtr, ParseValue * pvPtr);
+extern void Blt_ExpandParseValue(ParseValue *pvPtr, int needed);
+
+#endif
diff --git a/tlt3.0/bltPool.c b/tlt3.0/bltPool.c
new file mode 100644
index 0000000..8042a67
--- /dev/null
+++ b/tlt3.0/bltPool.c
@@ -0,0 +1,474 @@
+/*
+ * bltPool.c --
+ *
+ * Copyright 2001-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+
+#include "bltInt.h"
+#include "bltPool.h"
+
+/*
+ * Blt_Pool --
+ *
+ * Implements a pool memory allocator.
+ *
+ * + It's faster allocating memory since malloc/free are called
+ * only a fraction of the normal times. Fixed size items can
+ * be reused without deallocating/reallocating memory.
+ * + You don't have the extra 8-16 byte overhead per malloc.
+ * - Memory is freed only when the entire pool is destroyed.
+ * - Memory is allocated in chunks. More memory is allocated
+ * than used.
+ * 0 Depending upon allocation/deallocation patterns, locality
+ * may be improved or degraded.
+ *
+ * The pool is a chain of malloc'ed blocks.
+ *
+ * +---------+ +---------+ +---------+
+ * NULL<-| nextPtr |<-| nextPtr |<-| nextPtr |<- headPtr
+ * |---------| |---------| |---------|
+ * | chunk1 | | chunk2 | | chunk3 |
+ * +---------+ | | | |
+ * +---------+ | |
+ * | |
+ * | |
+ * +---------+
+ *
+ * Each chunk contains an integral number of fixed size items.
+ * The number of items doubles until a maximum size is reached
+ * (each subsequent new chunk will be the maximum). Chunks
+ * are allocated only when needed (no more space is available
+ * in the last chunk).
+ *
+ * The chain of blocks is only freed when the entire pool is
+ * destroyed.
+ *
+ * A freelist of unused items also maintained. Each freed item
+ * is prepended to a free list. Before allocating new chunks
+ * the freelist is examined to see if any unused items exist.
+ *
+ * chunk1 chunk2 chunk3
+ * +---------+ +---------+ +---------+
+ * NULL<-| unused | | | | |
+ * +----^----+ +---------+ +---------+
+ * | unused |<-| unused |<-| unused |
+ * +---------+ +---------+ +----^----+
+ * | | | | | unused |
+ * +---------+ | | +----^----+
+ * | | | | |
+ * +---------+ +----|----+
+ * | usused |<- freePtr
+ * +---------+
+ */
+
+#define POOL_MAX_CHUNK_SIZE ((1<<16) - sizeof(PoolChain))
+
+#ifndef ALIGN
+#define ALIGN(a) \
+ (((size_t)a + (sizeof(void *) - 1)) & (~(sizeof(void *) - 1)))
+#endif /* ALIGN */
+
+typedef struct _PoolChain {
+ struct _PoolChain *nextPtr;
+} PoolChain;
+
+typedef struct {
+ Blt_PoolAllocProc *allocProc;
+ Blt_PoolFreeProc *freeProc;
+
+ PoolChain *headPtr; /* Chain of malloc'ed chunks. */
+ PoolChain *freePtr; /* List of deleted items. This is only used
+ * for fixed size items. */
+ size_t poolSize; /* Log2 of # of items in the current block. */
+ size_t itemSize; /* Size of an item. */
+ size_t bytesLeft; /* # of bytes left in the current chunk. */
+ size_t waste;
+} Pool;
+
+static Blt_PoolAllocProc VariablePoolAllocItem;
+static Blt_PoolFreeProc VariablePoolFreeItem;
+static Blt_PoolAllocProc FixedPoolAllocItem;
+static Blt_PoolFreeProc FixedPoolFreeItem;
+static Blt_PoolAllocProc StringPoolAllocItem;
+static Blt_PoolFreeProc StringPoolFreeItem;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VariablePoolAllocItem --
+ *
+ * Returns a new item. First check if there is any more space
+ * left in the current chunk. If there isn't then next check
+ * the free list for unused items. Finally allocate a new
+ * chunk and return its first item.
+ *
+ * Results:
+ * Returns a new (possible reused) item.
+ *
+ * Side Effects:
+ * A new memory chunk may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+VariablePoolAllocItem(
+ Blt_Pool pool,
+ size_t size) /* Number of bytes to allocate. */
+{
+ Pool *poolPtr = (Pool *)pool;
+ PoolChain *chainPtr;
+ void *memory;
+
+ size = ALIGN(size);
+ if (size >= POOL_MAX_CHUNK_SIZE) {
+ /*
+ * Handle oversized requests by allocating a chunk to hold the
+ * single item and immediately placing it into the in-use list.
+ */
+ chainPtr = malloc(sizeof(PoolChain) + size);
+ if (poolPtr->headPtr == NULL) {
+ poolPtr->headPtr = chainPtr;
+ } else {
+ chainPtr->nextPtr = poolPtr->headPtr->nextPtr;
+ poolPtr->headPtr->nextPtr = chainPtr;
+ }
+ memory = (void *)chainPtr;
+ } else {
+ if (poolPtr->bytesLeft >= size) {
+ poolPtr->bytesLeft -= size;
+ memory = (char *)(poolPtr->headPtr + 1) + poolPtr->bytesLeft;
+ } else {
+ poolPtr->waste += poolPtr->bytesLeft;
+ /* Create a new block of items and prepend it to the in-use list */
+ poolPtr->bytesLeft = POOL_MAX_CHUNK_SIZE;
+ /* Allocate the requested chunk size, plus the header */
+ chainPtr = malloc(sizeof(PoolChain) + poolPtr->bytesLeft);
+ chainPtr->nextPtr = poolPtr->headPtr;
+ poolPtr->headPtr = chainPtr;
+ /* Peel off a new item. */
+ poolPtr->bytesLeft -= size;
+ memory = (char *)(chainPtr + 1) + poolPtr->bytesLeft;
+ }
+ }
+ return memory;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VariablePoolFreeItem --
+ *
+ * Placeholder for freeProc routine. The pool memory is
+ * not reclaimed or freed until the entire pool is released.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+VariablePoolFreeItem(Blt_Pool pool, void *item)
+{
+ /* Does nothing */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * StringPoolAllocItem --
+ *
+ * Returns a new item. First check if there is any more space
+ * left in the current chunk. If there isn't then next check
+ * the free list for unused items. Finally allocate a new
+ * chunk and return its first item.
+ *
+ * Results:
+ * Returns a new (possible reused) item.
+ *
+ * Side Effects:
+ * A new memory chunk may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+StringPoolAllocItem(Blt_Pool pool, size_t size)
+{
+ Pool *poolPtr = (Pool *)pool;
+ PoolChain *chainPtr;
+ void *memory;
+
+ if (size >= POOL_MAX_CHUNK_SIZE) {
+ /*
+ * Handle oversized requests by allocating a chunk to hold the
+ * single item and immediately placing it into the in-use list.
+ */
+ chainPtr = malloc(sizeof(PoolChain) + size);
+ if (poolPtr->headPtr == NULL) {
+ poolPtr->headPtr = chainPtr;
+ } else {
+ chainPtr->nextPtr = poolPtr->headPtr->nextPtr;
+ poolPtr->headPtr->nextPtr = chainPtr;
+ }
+ memory = (void *)chainPtr;
+ } else {
+ if (poolPtr->bytesLeft >= size) {
+ poolPtr->bytesLeft -= size;
+ memory = (char *)(poolPtr->headPtr + 1) + poolPtr->bytesLeft;
+ } else {
+ poolPtr->waste += poolPtr->bytesLeft;
+ /* Create a new block of items and prepend it to the
+ * in-use list */
+ poolPtr->bytesLeft = POOL_MAX_CHUNK_SIZE;
+ /* Allocate the requested chunk size, plus the header */
+ chainPtr = malloc(sizeof(PoolChain) + poolPtr->bytesLeft);
+ chainPtr->nextPtr = poolPtr->headPtr;
+ poolPtr->headPtr = chainPtr;
+ /* Peel off a new item. */
+ poolPtr->bytesLeft -= size;
+ memory = (char *)(chainPtr + 1) + poolPtr->bytesLeft;
+ }
+ }
+ return memory;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * StringPoolFreeItem --
+ *
+ * Placeholder for freeProc routine. String pool memory is
+ * not reclaimed or freed until the entire pool is released.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static void
+StringPoolFreeItem(Blt_Pool pool, void *item)
+{
+ /* Does nothing */
+}
+
+/*
+ * The fixed size pool is a chain of malloc'ed blocks.
+ *
+ * +---------+ +---------+ +---------+
+ * NULL<-| nextPtr |<-| nextPtr |<-| nextPtr |<- headPtr
+ * |---------| |---------| |---------|
+ * | chunk1 | | chunk2 | | chunk3 |
+ * +---------+ | | | |
+ * +---------+ | |
+ * | |
+ * | |
+ * +---------+
+ *
+ * Each chunk contains an integral number of fixed size items.
+ * The number of items doubles until a maximum size is reached
+ * (each subsequent new chunk will be the maximum). Chunks
+ * are allocated only when needed (no more space is available
+ * in the last chunk).
+ *
+ * The chain of blocks is only freed when the entire pool is
+ * destroyed.
+ *
+ * A freelist of unused items also maintained. Each freed item
+ * is prepended to a free list. Before allocating new chunks
+ * the freelist is examined to see if an unused items exist.
+ *
+ * chunk1 chunk2 chunk3
+ * +---------+ +---------+ +---------+
+ * NULL<-| unused | | | | |
+ * +----^----+ +---------+ +---------+
+ * | unused |<-| unused |<-| unused |
+ * +---------+ +---------+ +----^----+
+ * | | | | | unused |
+ * +---------+ | | +----^----+
+ * | | | | |
+ * +---------+ +----|----+
+ * | usused |<- freePtr
+ * +---------+
+ */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FixedPoolFreeItem --
+ *
+ * Returns a new item. First check if there is any more space
+ * left in the current chunk. If there isn't then next check
+ * the free list for unused items. Finally allocate a new
+ * chunk and return its first item.
+ *
+ * Results:
+ * Returns a new (possible reused) item.
+ *
+ * Side Effects:
+ * A new memory chunk may be allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void *
+FixedPoolAllocItem(Blt_Pool pool, size_t size)
+{
+ Pool *poolPtr = (Pool *)pool;
+ PoolChain *chainPtr;
+ void *newPtr;
+
+ size = ALIGN(size);
+ if (poolPtr->itemSize == 0) {
+ poolPtr->itemSize = size;
+ }
+ assert(size == poolPtr->itemSize);
+
+ if (poolPtr->bytesLeft > 0) {
+ poolPtr->bytesLeft -= poolPtr->itemSize;
+ newPtr = (char *)(poolPtr->headPtr + 1) + poolPtr->bytesLeft;
+ } else if (poolPtr->freePtr != NULL) { /* Reuse from the free list. */
+ /* Reuse items on the free list */
+ chainPtr = poolPtr->freePtr;
+ poolPtr->freePtr = chainPtr->nextPtr;
+ newPtr = (void *)chainPtr;
+ } else { /* Allocate another block. */
+
+ /* Create a new block of items and prepend it to the in-use list */
+ poolPtr->bytesLeft = poolPtr->itemSize * (1 << poolPtr->poolSize);
+ if (poolPtr->bytesLeft < POOL_MAX_CHUNK_SIZE) {
+ poolPtr->poolSize++; /* Keep doubling the size of the new
+ * chunk up to a maximum size. */
+ }
+ /* Allocate the requested chunk size, plus the header */
+ chainPtr = malloc(sizeof(PoolChain) + poolPtr->bytesLeft);
+ chainPtr->nextPtr = poolPtr->headPtr;
+ poolPtr->headPtr = chainPtr;
+
+ /* Peel off a new item. */
+ poolPtr->bytesLeft -= poolPtr->itemSize;
+ newPtr = (char *)(poolPtr->headPtr + 1) + poolPtr->bytesLeft;
+ }
+ return newPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FixedPoolFreeItem --
+ *
+ * Frees an item. The actual memory is not freed. The item
+ * instead is prepended to a freelist where it may be reclaimed
+ * and used again.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Item is placed on the pool's free list.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+FixedPoolFreeItem(Blt_Pool pool, void *item)
+{
+ Pool *poolPtr = (Pool *)pool;
+ PoolChain *chainPtr = (PoolChain *)item;
+
+ /* Prepend the newly deallocated item to the free list. */
+ chainPtr->nextPtr = poolPtr->freePtr;
+ poolPtr->freePtr = chainPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_PoolCreate --
+ *
+ * Creates a new memory pool for fixed-size/variable-size/string
+ * items.
+ *
+ * Results:
+ * Returns a pointer to the newly allocated pool.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Blt_Pool
+Blt_PoolCreate(int type)
+{
+ Pool *poolPtr;
+
+ poolPtr = malloc(sizeof(Pool));
+ switch (type) {
+ case BLT_VARIABLE_SIZE_ITEMS:
+ poolPtr->allocProc = VariablePoolAllocItem;
+ poolPtr->freeProc = VariablePoolFreeItem;
+ break;
+ case BLT_FIXED_SIZE_ITEMS:
+ poolPtr->allocProc = FixedPoolAllocItem;
+ poolPtr->freeProc = FixedPoolFreeItem;
+ break;
+ case BLT_STRING_ITEMS:
+ poolPtr->allocProc = StringPoolAllocItem;
+ poolPtr->freeProc = StringPoolFreeItem;
+ break;
+ }
+ poolPtr->headPtr = poolPtr->freePtr = NULL;
+ poolPtr->waste = poolPtr->bytesLeft = 0;
+ poolPtr->poolSize = poolPtr->itemSize = 0;
+ return (Blt_Pool)poolPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_PoolDestroy --
+ *
+ * Destroys the given memory pool. The chain of allocated blocks
+ * are freed. The is the only time that memory is actually freed.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * All memory used by the pool is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_PoolDestroy(Blt_Pool pool)
+{
+ Pool *poolPtr = (Pool *)pool;
+ PoolChain *chainPtr, *nextPtr;
+
+ for (chainPtr = poolPtr->headPtr; chainPtr != NULL; chainPtr = nextPtr) {
+ nextPtr = chainPtr->nextPtr;
+ free(chainPtr);
+ }
+ free(poolPtr);
+}
+
diff --git a/tlt3.0/bltPool.h b/tlt3.0/bltPool.h
new file mode 100644
index 0000000..5adf0a5
--- /dev/null
+++ b/tlt3.0/bltPool.h
@@ -0,0 +1,23 @@
+#ifndef BLT_POOL_H
+#define BLT_POOL_H
+
+#define BLT_STRING_ITEMS 0
+#define BLT_FIXED_SIZE_ITEMS 1
+#define BLT_VARIABLE_SIZE_ITEMS 2
+
+typedef struct _Blt_Pool *Blt_Pool;
+typedef void *(Blt_PoolAllocProc)(Blt_Pool pool, size_t size);
+typedef void (Blt_PoolFreeProc)(Blt_Pool pool, void *item);
+
+struct _Blt_Pool {
+ Blt_PoolAllocProc *allocProc;
+ Blt_PoolFreeProc *freeProc;
+};
+
+extern Blt_Pool Blt_PoolCreate(int type);
+extern void Blt_PoolDestroy(Blt_Pool pool);
+
+#define Blt_PoolAllocItem(pool, n) (*((pool)->allocProc))(pool, n)
+#define Blt_PoolFreeItem(pool, item) (*((pool)->freeProc))(pool, item)
+
+#endif /* BLT_POOL_H */
diff --git a/tlt3.0/bltPs.c b/tlt3.0/bltPs.c
new file mode 100644
index 0000000..b9f4c68
--- /dev/null
+++ b/tlt3.0/bltPs.c
@@ -0,0 +1,1328 @@
+/*
+ * bltPs.c --
+ *
+ * This module implements general PostScript conversion routines.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <stdarg.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+
+#include <tkPort.h>
+#include <tkInt.h>
+#include <tk3d.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltDBuffer.h"
+#include "bltPsInt.h"
+
+#define PS_MAXPATH 1500 /* Maximum number of components in a
+ * PostScript (level 1) path. */
+
+#define PICA_MM 2.83464566929
+#define PICA_INCH 72.0
+#define PICA_CM 28.3464566929
+
+static Tcl_Interp *psInterp = NULL;
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ps_GetPica --
+ *
+ * Given a string, returns the number of pica corresponding to that
+ * string.
+ *
+ * Results:
+ * The return value is a standard TCL return result. If TCL_OK is
+ * returned, then everything went well and the pixel distance is stored
+ * at *doublePtr; otherwise TCL_ERROR is returned and an error message is
+ * left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Ps_GetPicaFromObj(
+ Tcl_Interp *interp, /* Use this for error reporting. */
+ Tcl_Obj *objPtr, /* String describing a number of
+ * pixels. */
+ int *picaPtr) /* Place to store converted result. */
+{
+ char *p;
+ double pica;
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ pica = strtod((char *)string, &p);
+ if (p == string) {
+ goto error;
+ }
+ if (pica < 0.0) {
+ goto error;
+ }
+ while ((*p != '\0') && isspace((unsigned char)(*p))) {
+ p++;
+ }
+ switch (*p) {
+ case '\0': break;
+ case 'c': pica *= PICA_CM; p++; break;
+ case 'i': pica *= PICA_INCH; p++; break;
+ case 'm': pica *= PICA_MM; p++; break;
+ case 'p': p++; break;
+ default: goto error;
+ }
+ while ((*p != '\0') && isspace((unsigned char)(*p))) {
+ p++;
+ }
+ if (*p == '\0') {
+ *picaPtr = ROUND(pica);
+ return TCL_OK;
+ }
+ error:
+ Tcl_AppendResult(interp, "bad screen distance \"", string, "\"",
+ (char *) NULL);
+ return TCL_ERROR;
+}
+
+int
+Blt_Ps_GetPadFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back
+ * to */
+ Tcl_Obj *objPtr, /* Pixel value string */
+ Blt_Pad *padPtr)
+{
+ int side1, side2;
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc < 1) || (objc > 2)) {
+ Tcl_AppendResult(interp, "wrong # elements in padding list",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_Ps_GetPicaFromObj(interp, objv[0], &side1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ side2 = side1;
+ if ((objc > 1) &&
+ (Blt_Ps_GetPicaFromObj(interp, objv[1], &side2) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ /* Don't update the pad structure until we know both values are okay. */
+ padPtr->side1 = side1;
+ padPtr->side2 = side2;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ps_ComputeBoundingBox --
+ *
+ * Computes the bounding box for the PostScript plot. First get the size
+ * of the plot (by default, it's the size of graph's X window). If the
+ * plot plus the page border is bigger than the designated paper size, or
+ * if the "-maxpect" option is turned on, scale the plot to the page.
+ *
+ * Note: All coordinates/sizes are in screen coordinates, not PostScript
+ * coordinates. This includes the computed bounding box and paper
+ * size. They will be scaled to printer points later.
+ *
+ * Results:
+ * Returns the height of the paper in screen coordinates.
+ *
+ * Side Effects:
+ * The graph dimensions (width and height) are changed to the requested
+ * PostScript plot size.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Ps_ComputeBoundingBox(PageSetup *setupPtr, int width, int height)
+{
+ int paperWidth, paperHeight;
+ int x, y, hSize, vSize, hBorder, vBorder;
+ float hScale, vScale, scale;
+
+ x = setupPtr->padLeft;
+ y = setupPtr->padTop;
+
+ hBorder = PADDING(setupPtr->xPad);
+ vBorder = PADDING(setupPtr->yPad);
+
+ if (setupPtr->flags & PS_LANDSCAPE) {
+ hSize = height;
+ vSize = width;
+ } else {
+ hSize = width;
+ vSize = height;
+ }
+ /*
+ * If the paper size wasn't specified, set it to the graph size plus the
+ * paper border.
+ */
+ paperWidth = (setupPtr->reqPaperWidth > 0) ? setupPtr->reqPaperWidth :
+ hSize + hBorder;
+ paperHeight = (setupPtr->reqPaperHeight > 0) ? setupPtr->reqPaperHeight :
+ vSize + vBorder;
+
+ /*
+ * Scale the plot size (the graph itself doesn't change size) if it's
+ * bigger than the paper or if -maxpect was set.
+ */
+ hScale = vScale = 1.0f;
+ if ((setupPtr->flags & PS_MAXPECT) || ((hSize + hBorder) > paperWidth)) {
+ hScale = (float)(paperWidth - hBorder) / (float)hSize;
+ }
+ if ((setupPtr->flags & PS_MAXPECT) || ((vSize + vBorder) > paperHeight)) {
+ vScale = (float)(paperHeight - vBorder) / (float)vSize;
+ }
+ scale = MIN(hScale, vScale);
+ if (scale != 1.0f) {
+ hSize = (int)((hSize * scale) + 0.5f);
+ vSize = (int)((vSize * scale) + 0.5f);
+ }
+ setupPtr->scale = scale;
+ if (setupPtr->flags & PS_CENTER) {
+ if (paperWidth > hSize) {
+ x = (paperWidth - hSize) / 2;
+ }
+ if (paperHeight > vSize) {
+ y = (paperHeight - vSize) / 2;
+ }
+ }
+ setupPtr->left = x;
+ setupPtr->bottom = y;
+ setupPtr->right = x + hSize - 1;
+ setupPtr->top = y + vSize - 1;
+ setupPtr->paperHeight = paperHeight;
+ setupPtr->paperWidth = paperWidth;
+ return paperHeight;
+}
+
+PostScript *
+Blt_Ps_Create(Tcl_Interp *interp, PageSetup *setupPtr)
+{
+ PostScript *psPtr;
+
+ psPtr = malloc(sizeof(PostScript));
+ psPtr->setupPtr = setupPtr;
+ psPtr->interp = interp;
+ Tcl_DStringInit(&psPtr->dString);
+ return psPtr;
+}
+
+void
+Blt_Ps_SetPrinting(PostScript *psPtr, int state)
+{
+ psInterp = ((state) && (psPtr != NULL)) ? psPtr->interp : NULL;
+}
+
+int
+Blt_Ps_IsPrinting(void)
+{
+ return (psInterp != NULL);
+}
+
+void
+Blt_Ps_Free(PostScript *psPtr)
+{
+ Tcl_DStringFree(&psPtr->dString);
+ free(psPtr);
+}
+
+const char *
+Blt_Ps_GetValue(PostScript *psPtr, int *lengthPtr)
+{
+ *lengthPtr = strlen(Tcl_DStringValue(&psPtr->dString));
+ return Tcl_DStringValue(&psPtr->dString);
+}
+
+void
+Blt_Ps_SetInterp(PostScript *psPtr, Tcl_Interp *interp)
+{
+ Tcl_DStringResult(interp, &psPtr->dString);
+}
+
+char *
+Blt_Ps_GetScratchBuffer(PostScript *psPtr)
+{
+ return psPtr->scratchArr;
+}
+
+Tcl_Interp *
+Blt_Ps_GetInterp(PostScript *psPtr)
+{
+ return psPtr->interp;
+}
+
+Tcl_DString *
+Blt_Ps_GetDString(PostScript *psPtr)
+{
+ return &psPtr->dString;
+}
+
+int
+Blt_Ps_SaveFile(Tcl_Interp *interp, PostScript *psPtr, const char *fileName)
+{
+ Tcl_Channel channel;
+ int nWritten, nBytes;
+ char *bytes;
+
+ channel = Tcl_OpenFileChannel(interp, fileName, "w", 0660);
+ if (channel == NULL) {
+ return TCL_ERROR;
+ }
+ nBytes = Tcl_DStringLength(&psPtr->dString);
+ bytes = Tcl_DStringValue(&psPtr->dString);
+ nWritten = Tcl_Write(channel, bytes, nBytes);
+ Tcl_Close(interp, channel);
+ if (nWritten != nBytes) {
+ Tcl_AppendResult(interp, "short file \"", fileName, (char *)NULL);
+ Tcl_AppendResult(interp, "\" : wrote ", Blt_Itoa(nWritten), " of ",
+ (char *)NULL);
+ Tcl_AppendResult(interp, Blt_Itoa(nBytes), " bytes.", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+void
+Blt_Ps_VarAppend
+TCL_VARARGS_DEF(PostScript *, arg1)
+{
+ va_list argList;
+ PostScript *psPtr;
+ const char *string;
+
+ psPtr = TCL_VARARGS_START(PostScript, arg1, argList);
+ for (;;) {
+ string = va_arg(argList, char *);
+ if (string == NULL) {
+ break;
+ }
+ Tcl_DStringAppend(&psPtr->dString, string, -1);
+ }
+}
+
+void
+Blt_Ps_AppendBytes(PostScript *psPtr, const char *bytes, int length)
+{
+ Tcl_DStringAppend(&psPtr->dString, bytes, length);
+}
+
+void
+Blt_Ps_Append(PostScript *psPtr, const char *string)
+{
+ Tcl_DStringAppend(&psPtr->dString, string, -1);
+}
+
+void
+Blt_Ps_Format
+TCL_VARARGS_DEF(PostScript *, arg1)
+{
+ va_list argList;
+ PostScript *psPtr;
+ char *fmt;
+
+ psPtr = TCL_VARARGS_START(PostScript, arg1, argList);
+ fmt = va_arg(argList, char *);
+ vsnprintf(psPtr->scratchArr, POSTSCRIPT_BUFSIZ, fmt, argList);
+ va_end(argList);
+ Tcl_DStringAppend(&psPtr->dString, psPtr->scratchArr, -1);
+}
+
+int
+Blt_Ps_IncludeFile(Tcl_Interp *interp, Blt_Ps ps, const char *fileName)
+{
+ Tcl_Channel channel;
+ Tcl_DString dString;
+ char *buf;
+ char *libDir;
+ int nBytes;
+
+ buf = Blt_Ps_GetScratchBuffer(ps);
+
+ /*
+ * Read in a standard prolog file from file and append it to the
+ * PostScript output stored in the Tcl_DString in psPtr.
+ */
+
+ libDir = (char *)Tcl_GetVar(interp, "tlt_library", TCL_GLOBAL_ONLY);
+ if (libDir == NULL) {
+ Tcl_AppendResult(interp, "couldn't find TLT script library:",
+ "global variable \"tlt_library\" doesn't exist", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Tcl_DStringInit(&dString);
+ Tcl_DStringAppend(&dString, libDir, -1);
+ Tcl_DStringAppend(&dString, "/", -1);
+ Tcl_DStringAppend(&dString, fileName, -1);
+ fileName = Tcl_DStringValue(&dString);
+ Blt_Ps_VarAppend(ps, "\n% including file \"", fileName, "\"\n\n",
+ (char *)NULL);
+ channel = Tcl_OpenFileChannel(interp, fileName, "r", 0);
+ if (channel == NULL) {
+ Tcl_AppendResult(interp, "couldn't open prologue file \"", fileName,
+ "\": ", Tcl_PosixError(interp), (char *)NULL);
+ return TCL_ERROR;
+ }
+ for(;;) {
+ nBytes = Tcl_Read(channel, buf, POSTSCRIPT_BUFSIZ);
+ if (nBytes < 0) {
+ Tcl_AppendResult(interp, "error reading prologue file \"",
+ fileName, "\": ", Tcl_PosixError(interp),
+ (char *)NULL);
+ Tcl_Close(interp, channel);
+ Tcl_DStringFree(&dString);
+ return TCL_ERROR;
+ }
+ if (nBytes == 0) {
+ break;
+ }
+ buf[nBytes] = '\0';
+ Blt_Ps_Append(ps, buf);
+ }
+ Tcl_DStringFree(&dString);
+ Tcl_Close(interp, channel);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * XColorToPostScript --
+ *
+ * Convert the a XColor (from its RGB values) to a PostScript command.
+ * If a Tk color map variable exists, it will be consulted for a
+ * PostScript translation based upon the color name.
+ *
+ * Maps an X color intensity (0 to 2^16-1) to a floating point value
+ * [0..1]. Many versions of Tk don't properly handle the the lower 8
+ * bits of the color intensity, so we can only consider the upper 8 bits.
+ *
+ * Results:
+ * The string representing the color mode is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+XColorToPostScript(Blt_Ps ps, XColor *colorPtr)
+{
+ /*
+ * Shift off the lower byte before dividing because some versions of Tk
+ * don't fill the lower byte correctly.
+ */
+ Blt_Ps_Format(ps, "%g %g %g",
+ ((double)(colorPtr->red >> 8) / 255.0),
+ ((double)(colorPtr->green >> 8) / 255.0),
+ ((double)(colorPtr->blue >> 8) / 255.0));
+}
+
+void
+Blt_Ps_XSetBackground(PostScript *psPtr, XColor *colorPtr)
+{
+ /* If the color name exists in TCL array variable, use that translation */
+ if ((psPtr->setupPtr != NULL) && (psPtr->setupPtr->colorVarName != NULL)) {
+ const char *psColor;
+
+ psColor = Tcl_GetVar2(psPtr->interp, psPtr->setupPtr->colorVarName,
+ Tk_NameOfColor(colorPtr), 0);
+ if (psColor != NULL) {
+ Blt_Ps_VarAppend(psPtr, " ", psColor, "\n", (char *)NULL);
+ return;
+ }
+ }
+ XColorToPostScript(psPtr, colorPtr);
+ Blt_Ps_Append(psPtr, " setrgbcolor\n");
+ if (psPtr->setupPtr->flags & PS_GREYSCALE) {
+ Blt_Ps_Append(psPtr, " currentgray setgray\n");
+ }
+}
+
+void
+Blt_Ps_XSetForeground(PostScript *psPtr, XColor *colorPtr)
+{
+ /* If the color name exists in TCL array variable, use that translation */
+ if ((psPtr->setupPtr != NULL) && (psPtr->setupPtr->colorVarName != NULL)) {
+ const char *psColor;
+
+ psColor = Tcl_GetVar2(psPtr->interp, psPtr->setupPtr->colorVarName,
+ Tk_NameOfColor(colorPtr), 0);
+ if (psColor != NULL) {
+ Blt_Ps_VarAppend(psPtr, " ", psColor, "\n", (char *)NULL);
+ return;
+ }
+ }
+ XColorToPostScript(psPtr, colorPtr);
+ Blt_Ps_Append(psPtr, " setrgbcolor\n");
+ if (psPtr->setupPtr->flags & PS_GREYSCALE) {
+ Blt_Ps_Append(psPtr, " currentgray setgray\n");
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ReverseBits --
+ *
+ * Convert a byte from a X image into PostScript image order. This
+ * requires not only the nybbles to be reversed but also their bit
+ * values.
+ *
+ * Results:
+ * The converted byte is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+INLINE static unsigned char
+ReverseBits(unsigned char byte)
+{
+ byte = ((byte >> 1) & 0x55) | ((byte << 1) & 0xaa);
+ byte = ((byte >> 2) & 0x33) | ((byte << 2) & 0xcc);
+ byte = ((byte >> 4) & 0x0f) | ((byte << 4) & 0xf0);
+ return byte;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ByteToHex --
+ *
+ * Convert a byte to its ASCII hexidecimal equivalent.
+ *
+ * Results:
+ * The converted 2 ASCII character string is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+INLINE static void
+ByteToHex(unsigned char byte, char *string)
+{
+ static char hexDigits[] = "0123456789ABCDEF";
+
+ string[0] = hexDigits[byte >> 4];
+ string[1] = hexDigits[byte & 0x0F];
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ps_XSetBitmapData --
+ *
+ * Output a PostScript image string of the given bitmap image. It is
+ * assumed the image is one bit deep and a zero value indicates an
+ * off-pixel. To convert to PostScript, the bits need to be reversed
+ * from the X11 image order.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The PostScript image string is appended to interp->result.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ps_XSetBitmapData(Blt_Ps ps, Display *display, Pixmap bitmap, int w, int h)
+{
+ XImage *imagePtr;
+ int byteCount;
+ int y, bitPos;
+
+ imagePtr = XGetImage(display, bitmap, 0, 0, w, h, 1, ZPixmap);
+ Blt_Ps_Append(ps, "\t<");
+ byteCount = bitPos = 0; /* Suppress compiler warning */
+ for (y = 0; y < h; y++) {
+ unsigned char byte;
+ char string[10];
+ int x;
+
+ byte = 0;
+ for (x = 0; x < w; x++) {
+ unsigned long pixel;
+
+ pixel = XGetPixel(imagePtr, x, y);
+ bitPos = x % 8;
+ byte |= (unsigned char)(pixel << bitPos);
+ if (bitPos == 7) {
+ byte = ReverseBits(byte);
+ ByteToHex(byte, string);
+ string[2] = '\0';
+ byteCount++;
+ byte = 0;
+ if (byteCount >= 30) {
+ string[2] = '\n';
+ string[3] = '\t';
+ string[4] = '\0';
+ byteCount = 0;
+ }
+ Blt_Ps_Append(ps, string);
+ }
+ } /* x */
+ if (bitPos != 7) {
+ byte = ReverseBits(byte);
+ ByteToHex(byte, string);
+ string[2] = '\0';
+ Blt_Ps_Append(ps, string);
+ byteCount++;
+ }
+ } /* y */
+ Blt_Ps_Append(ps, ">\n");
+ XDestroyImage(imagePtr);
+}
+
+typedef struct {
+ const char *alias;
+ const char *fontName;
+} FamilyMap;
+
+static FamilyMap familyMap[] =
+{
+ { "Arial", "Helvetica" },
+ { "AvantGarde", "AvantGarde" },
+ { "Bookman", "Bookman" },
+ { "Courier New", "Courier" },
+ { "Courier", "Courier" },
+ { "Geneva", "Helvetica" },
+ { "Helvetica", "Helvetica" },
+ { "Mathematica1", "Helvetica" },
+ { "Monaco", "Courier" },
+ { "New Century Schoolbook", "NewCenturySchlbk" },
+ { "New York", "Times" },
+ { "Nimbus Roman No9 L" "Times" },
+ { "Nimbus Sans L Condensed","Helvetica" },
+ { "Nimbus Sans L", "Helvetica" },
+ { "Palatino", "Palatino" },
+ { "Standard Symbols L", "Symbol" },
+ { "Swiss 721", "Helvetica" },
+ { "Symbol", "Symbol" },
+ { "Times New Roman", "Times" },
+ { "Times Roman", "Times" },
+ { "Times", "Times" },
+ { "ZapfChancery", "ZapfChancery" },
+ { "ZapfDingbats", "ZapfDingbats" }
+};
+
+static int nFamilyNames = (sizeof(familyMap) / sizeof(FamilyMap));
+
+static const char *
+FamilyToPsFamily(const char *family)
+{
+ FamilyMap *fp, *fend;
+
+ if (strncasecmp(family, "itc ", 4) == 0) {
+ family += 4;
+ }
+ for (fp = familyMap, fend = fp + nFamilyNames; fp < fend; fp++) {
+ if (strcasecmp(fp->alias, family) == 0) {
+ return fp->fontName;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ * Routines to convert X drawing functions to PostScript commands.
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ps_SetClearBackground(Blt_Ps ps)
+{
+ Blt_Ps_Append(ps, "1 1 1 setrgbcolor\n");
+}
+
+void
+Blt_Ps_XSetCapStyle(Blt_Ps ps, int capStyle)
+{
+ /*
+ * X11:not last = 0, butt = 1, round = 2, projecting = 3
+ * PS: butt = 0, round = 1, projecting = 2
+ */
+ if (capStyle > 0) {
+ capStyle--;
+ }
+ Blt_Ps_Format(ps, "%d setlinecap\n", capStyle);
+}
+
+void
+Blt_Ps_XSetJoinStyle(Blt_Ps ps, int joinStyle)
+{
+ /*
+ * miter = 0, round = 1, bevel = 2
+ */
+ Blt_Ps_Format(ps, "%d setlinejoin\n", joinStyle);
+}
+
+void
+Blt_Ps_XSetLineWidth(Blt_Ps ps, int lineWidth)
+{
+ if (lineWidth < 1) {
+ lineWidth = 1;
+ }
+ Blt_Ps_Format(ps, "%d setlinewidth\n", lineWidth);
+}
+
+void
+Blt_Ps_XSetDashes(Blt_Ps ps, Blt_Dashes *dashesPtr)
+{
+
+ Blt_Ps_Append(ps, "[ ");
+ if (dashesPtr != NULL) {
+ unsigned char *vp;
+
+ for (vp = dashesPtr->values; *vp != 0; vp++) {
+ Blt_Ps_Format(ps, " %d", *vp);
+ }
+ }
+ Blt_Ps_Append(ps, "] 0 setdash\n");
+}
+
+void
+Blt_Ps_XSetLineAttributes(
+ Blt_Ps ps,
+ XColor *colorPtr,
+ int lineWidth,
+ Blt_Dashes *dashesPtr,
+ int capStyle,
+ int joinStyle)
+{
+ Blt_Ps_XSetJoinStyle(ps, joinStyle);
+ Blt_Ps_XSetCapStyle(ps, capStyle);
+ Blt_Ps_XSetForeground(ps, colorPtr);
+ Blt_Ps_XSetLineWidth(ps, lineWidth);
+ Blt_Ps_XSetDashes(ps, dashesPtr);
+ Blt_Ps_Append(ps, "/DashesProc {} def\n");
+}
+
+void
+Blt_Ps_Rectangle(Blt_Ps ps, int x, int y, int width, int height)
+{
+ Blt_Ps_Append(ps, "newpath\n");
+ Blt_Ps_Format(ps, " %d %d moveto\n", x, y);
+ Blt_Ps_Format(ps, " %d %d rlineto\n", width, 0);
+ Blt_Ps_Format(ps, " %d %d rlineto\n", 0, height);
+ Blt_Ps_Format(ps, " %d %d rlineto\n", -width, 0);
+ Blt_Ps_Append(ps, "closepath\n");
+}
+
+void
+Blt_Ps_XFillRectangle(Blt_Ps ps, double x, double y, int width, int height)
+{
+ Blt_Ps_Rectangle(ps, (int)x, (int)y, width, height);
+ Blt_Ps_Append(ps, "fill\n");
+}
+
+void
+Blt_Ps_PolylineFromXPoints(Blt_Ps ps, XPoint *points, int n)
+{
+ XPoint *pp, *pend;
+
+ pp = points;
+ Blt_Ps_Append(ps, "newpath\n");
+ Blt_Ps_Format(ps, " %d %d moveto\n", pp->x, pp->y);
+ pp++;
+ for (pend = points + n; pp < pend; pp++) {
+ Blt_Ps_Format(ps, " %d %d lineto\n", pp->x, pp->y);
+ }
+}
+
+void
+Blt_Ps_Polyline(Blt_Ps ps, Point2d *screenPts, int nScreenPts)
+{
+ Point2d *pp, *pend;
+
+ pp = screenPts;
+ Blt_Ps_Append(ps, "newpath\n");
+ Blt_Ps_Format(ps, " %g %g moveto\n", pp->x, pp->y);
+ for (pp++, pend = screenPts + nScreenPts; pp < pend; pp++) {
+ Blt_Ps_Format(ps, " %g %g lineto\n", pp->x, pp->y);
+ }
+}
+
+void
+Blt_Ps_Polygon(Blt_Ps ps, Point2d *screenPts, int nScreenPts)
+{
+ Point2d *pp, *pend;
+
+ pp = screenPts;
+ Blt_Ps_Append(ps, "newpath\n");
+ Blt_Ps_Format(ps, " %g %g moveto\n", pp->x, pp->y);
+ for (pp++, pend = screenPts + nScreenPts; pp < pend; pp++) {
+ Blt_Ps_Format(ps, " %g %g lineto\n", pp->x, pp->y);
+ }
+ Blt_Ps_Format(ps, " %g %g lineto\n", screenPts[0].x, screenPts[0].y);
+ Blt_Ps_Append(ps, "closepath\n");
+}
+
+void
+Blt_Ps_XFillPolygon(Blt_Ps ps, Point2d *screenPts, int nScreenPts)
+{
+ Blt_Ps_Polygon(ps, screenPts, nScreenPts);
+ Blt_Ps_Append(ps, "fill\n");
+}
+
+void
+Blt_Ps_XDrawSegments(Blt_Ps ps, XSegment *segments, int nSegments)
+{
+ XSegment *sp, *send;
+
+ for (sp = segments, send = sp + nSegments; sp < send; sp++) {
+ Blt_Ps_Format(ps, "%d %d moveto %d %d lineto\n", sp->x1, sp->y1,
+ sp->x2, sp->y2);
+ Blt_Ps_Append(ps, "DashesProc stroke\n");
+ }
+}
+
+
+void
+Blt_Ps_XFillRectangles(Blt_Ps ps, XRectangle *rectangles, int nRectangles)
+{
+ XRectangle *rp, *rend;
+
+ for (rp = rectangles, rend = rp + nRectangles; rp < rend; rp++) {
+ Blt_Ps_XFillRectangle(ps, (double)rp->x, (double)rp->y,
+ (int)rp->width, (int)rp->height);
+ }
+}
+
+#ifndef TK_RELIEF_SOLID
+#define TK_RELIEF_SOLID -1 /* Set the an impossible value. */
+#endif /* TK_RELIEF_SOLID */
+
+void
+Blt_Ps_Draw3DRectangle(
+ Blt_Ps ps,
+ Tk_3DBorder border, /* Token for border to draw. */
+ double x, double y, /* Coordinates of rectangle */
+ int width, int height, /* Region to be drawn. */
+ int borderWidth, /* Desired width for border, in pixels. */
+ int relief) /* Should be either TK_RELIEF_RAISED or
+ * TK_RELIEF_SUNKEN; indicates position of
+ * interior of window relative to exterior. */
+{
+ Point2d points[7];
+ TkBorder *borderPtr = (TkBorder *) border;
+ XColor *lightPtr, *darkPtr;
+ XColor *topPtr, *bottomPtr;
+ XColor light, dark;
+ int twiceWidth = (borderWidth * 2);
+
+ if ((width < twiceWidth) || (height < twiceWidth)) {
+ return;
+ }
+ if ((relief == TK_RELIEF_SOLID) ||
+ (borderPtr->lightColorPtr == NULL) || (borderPtr->darkColorPtr == NULL)) {
+ if (relief == TK_RELIEF_SOLID) {
+ dark.red = dark.blue = dark.green = 0x00;
+ light.red = light.blue = light.green = 0x00;
+ relief = TK_RELIEF_SUNKEN;
+ } else {
+ light = *borderPtr->bgColorPtr;
+ dark.red = dark.blue = dark.green = 0xFF;
+ }
+ lightPtr = &light;
+ darkPtr = &dark;
+ } else {
+ lightPtr = borderPtr->lightColorPtr;
+ darkPtr = borderPtr->darkColorPtr;
+ }
+
+
+ /* Handle grooves and ridges with recursive calls. */
+
+ if ((relief == TK_RELIEF_GROOVE) || (relief == TK_RELIEF_RIDGE)) {
+ int halfWidth, insideOffset;
+
+ halfWidth = borderWidth / 2;
+ insideOffset = borderWidth - halfWidth;
+ Blt_Ps_Draw3DRectangle(ps, border, (double)x, (double)y,
+ width, height, halfWidth,
+ (relief == TK_RELIEF_GROOVE) ? TK_RELIEF_SUNKEN : TK_RELIEF_RAISED);
+ Blt_Ps_Draw3DRectangle(ps, border,
+ (double)(x + insideOffset), (double)(y + insideOffset),
+ width - insideOffset * 2, height - insideOffset * 2, halfWidth,
+ (relief == TK_RELIEF_GROOVE) ? TK_RELIEF_RAISED : TK_RELIEF_SUNKEN);
+ return;
+ }
+ if (relief == TK_RELIEF_RAISED) {
+ topPtr = lightPtr;
+ bottomPtr = darkPtr;
+ } else if (relief == TK_RELIEF_SUNKEN) {
+ topPtr = darkPtr;
+ bottomPtr = lightPtr;
+ } else {
+ topPtr = bottomPtr = borderPtr->bgColorPtr;
+ }
+ Blt_Ps_XSetBackground(ps, bottomPtr);
+ Blt_Ps_XFillRectangle(ps, x, y + height - borderWidth, width, borderWidth);
+ Blt_Ps_XFillRectangle(ps, x + width - borderWidth, y, borderWidth, height);
+ points[0].x = points[1].x = points[6].x = x;
+ points[0].y = points[6].y = y + height;
+ points[1].y = points[2].y = y;
+ points[2].x = x + width;
+ points[3].x = x + width - borderWidth;
+ points[3].y = points[4].y = y + borderWidth;
+ points[4].x = points[5].x = x + borderWidth;
+ points[5].y = y + height - borderWidth;
+ if (relief != TK_RELIEF_FLAT) {
+ Blt_Ps_XSetBackground(ps, topPtr);
+ }
+ Blt_Ps_XFillPolygon(ps, points, 7);
+}
+
+void
+Blt_Ps_Fill3DRectangle(
+ Blt_Ps ps,
+ Tk_3DBorder border, /* Token for border to draw. */
+ double x, double y, /* Coordinates of top-left of border area */
+ int width, int height, /* Dimension of border to be drawn. */
+ int borderWidth, /* Desired width for border, in pixels. */
+ int relief) /* Should be either TK_RELIEF_RAISED or
+ * TK_RELIEF_SUNKEN; indicates position of
+ * interior of window relative to exterior. */
+{
+ TkBorder *borderPtr = (TkBorder *) border;
+
+ Blt_Ps_XSetBackground(ps, borderPtr->bgColorPtr);
+ Blt_Ps_XFillRectangle(ps, x, y, width, height);
+ Blt_Ps_Draw3DRectangle(ps, border, x, y, width, height, borderWidth,
+ relief);
+}
+
+void
+Blt_Ps_XSetStipple(Blt_Ps ps, Display *display, Pixmap bitmap)
+{
+ int width, height;
+
+ Tk_SizeOfBitmap(display, bitmap, &width, &height);
+ Blt_Ps_Format(ps,
+ "gsave\n"
+ " clip\n"
+ " %d %d\n",
+ width, height);
+ Blt_Ps_XSetBitmapData(ps, display, bitmap, width, height);
+ Blt_Ps_VarAppend(ps,
+ " StippleFill\n"
+ "grestore\n", (char *)NULL);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ps_XSetFont --
+ *
+ * Map the Tk font to a PostScript font and point size.
+ *
+ * If a TCL array variable was specified, each element should be indexed
+ * by the X11 font name and contain a list of 1-2 elements; the
+ * PostScript font name and the desired point size. The point size may
+ * be omitted and the X font point size will be used.
+ *
+ * Otherwise, if the foundry is "Adobe", we try to do a plausible mapping
+ * looking at the full name of the font and building a string in the form
+ * of "Family-TypeFace".
+ *
+ * Returns:
+ * None.
+ *
+ * Side Effects:
+ * PostScript commands are output to change the type and the point size
+ * of the current font.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Blt_Ps_XSetFont(PostScript *psPtr, Blt_Font font)
+{
+ Tcl_Interp *interp = psPtr->interp;
+ const char *family;
+
+ /* Use the font variable information if it exists. */
+ if ((psPtr->setupPtr != NULL) && (psPtr->setupPtr->fontVarName != NULL)) {
+ char *value;
+
+ value = (char *)Tcl_GetVar2(interp, psPtr->setupPtr->fontVarName,
+ Blt_NameOfFont(font), 0);
+ if (value != NULL) {
+ const char **argv = NULL;
+ int argc;
+ int newSize;
+ double pointSize;
+ const char *fontName;
+
+ if (Tcl_SplitList(NULL, value, &argc, &argv) != TCL_OK) {
+ return;
+ }
+ fontName = argv[0];
+ if ((argc != 2) ||
+ (Tcl_GetInt(interp, argv[1], &newSize) != TCL_OK)) {
+ free(argv);
+ return;
+ }
+ pointSize = (double)newSize;
+ Blt_Ps_Format(psPtr, "%g /%s SetFont\n", pointSize,
+ fontName);
+ free(argv);
+ return;
+ }
+ /*FallThru*/
+ }
+
+ /*
+ * Check to see if it's a PostScript font. Tk_PostScriptFontName silently
+ * generates a bogus PostScript font name, so we have to check to see if
+ * this is really a PostScript font first before we call it.
+ */
+ family = FamilyToPsFamily(Blt_FamilyOfFont(font));
+ if (family != NULL) {
+ Tcl_DString dString;
+ double pointSize;
+
+ Tcl_DStringInit(&dString);
+ pointSize = (double)Blt_PostscriptFontName(font, &dString);
+ Blt_Ps_Format(psPtr, "%g /%s SetFont\n", pointSize,
+ Tcl_DStringValue(&dString));
+ Tcl_DStringFree(&dString);
+ return;
+ }
+ Blt_Ps_Append(psPtr, "12.0 /Helvetica-Bold SetFont\n");
+}
+
+static void
+TextLayoutToPostScript(Blt_Ps ps, int x, int y, TextLayout *textPtr)
+{
+ char *bp, *dst;
+ int count; /* Counts the # of bytes written to the
+ * intermediate scratch buffer. */
+ const char *src, *end;
+ TextFragment *fragPtr;
+ int i;
+ unsigned char c;
+#if HAVE_UTF
+ Tcl_UniChar ch;
+#endif
+ int limit;
+
+ limit = POSTSCRIPT_BUFSIZ - 4; /* High water mark for scratch buffer. */
+ fragPtr = textPtr->fragments;
+ for (i = 0; i < textPtr->nFrags; i++, fragPtr++) {
+ if (fragPtr->count < 1) {
+ continue;
+ }
+ Blt_Ps_Append(ps, "(");
+ count = 0;
+ dst = Blt_Ps_GetScratchBuffer(ps);
+ src = fragPtr->text;
+ end = fragPtr->text + fragPtr->count;
+ while (src < end) {
+ if (count > limit) {
+ /* Don't let the scatch buffer overflow */
+ dst = Blt_Ps_GetScratchBuffer(ps);
+ dst[count] = '\0';
+ Blt_Ps_Append(ps, dst);
+ count = 0;
+ }
+#if HAVE_UTF
+ /*
+ * INTL: For now we just treat the characters as binary data and
+ * display the lower byte. Eventually this should be revised to
+ * handle international postscript fonts.
+ */
+ src += Tcl_UtfToUniChar(src, &ch);
+ c = (unsigned char)(ch & 0xff);
+#else
+ c = *src++;
+#endif
+
+ if ((c == '\\') || (c == '(') || (c == ')')) {
+ /*
+ * If special PostScript characters characters "\", "(", and
+ * ")" are contained in the text string, prepend backslashes
+ * to them.
+ */
+ *dst++ = '\\';
+ *dst++ = c;
+ count += 2;
+ } else if ((c < ' ') || (c > '~')) {
+ /* Convert non-printable characters into octal. */
+ sprintf_s(dst, 5, "\\%03o", c);
+ dst += 4;
+ count += 4;
+ } else {
+ *dst++ = c;
+ count++;
+ }
+ }
+ bp = Blt_Ps_GetScratchBuffer(ps);
+ bp[count] = '\0';
+ Blt_Ps_Append(ps, bp);
+ Blt_Ps_Format(ps, ") %d %d %d DrawAdjText\n",
+ fragPtr->width, x + fragPtr->x, y + fragPtr->y);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ps_DrawText --
+ *
+ * Output PostScript commands to print a text string. The string may be
+ * rotated at any arbitrary angle, and placed according the anchor type
+ * given. The anchor indicates how to interpret the window coordinates as
+ * an anchor for the text bounding box.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Text string is drawn using the given font and GC on the graph window
+ * at the given coordinates, anchor, and rotation
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ps_DrawText(
+ Blt_Ps ps,
+ const char *string, /* String to convert to PostScript */
+ TextStyle *tsPtr, /* Text attribute information */
+ double x, double y) /* Window coordinates where to print text */
+{
+ TextLayout *textPtr;
+ Point2d t;
+
+ if ((string == NULL) || (*string == '\0')) { /* Empty string, do nothing */
+ return;
+ }
+ textPtr = Blt_Ts_CreateLayout(string, -1, tsPtr);
+ {
+ float angle;
+ double rw, rh;
+
+ angle = fmod(tsPtr->angle, (double)360.0);
+ Blt_GetBoundingBox(textPtr->width, textPtr->height, angle, &rw, &rh,
+ (Point2d *)NULL);
+ /*
+ * Find the center of the bounding box
+ */
+ t = Blt_AnchorPoint(x, y, rw, rh, tsPtr->anchor);
+ t.x += rw * 0.5;
+ t.y += rh * 0.5;
+ }
+
+ /* Initialize text (sets translation and rotation) */
+ Blt_Ps_Format(ps, "%d %d %g %g %g BeginText\n", textPtr->width,
+ textPtr->height, tsPtr->angle, t.x, t.y);
+
+ Blt_Ps_XSetFont(ps, tsPtr->font);
+
+ Blt_Ps_XSetForeground(ps, tsPtr->color);
+ TextLayoutToPostScript(ps, 0, 0, textPtr);
+ free(textPtr);
+ Blt_Ps_Append(ps, "EndText\n");
+}
+
+void
+Blt_Ps_XDrawLines(Blt_Ps ps, XPoint *points, int n)
+{
+ int nLeft;
+
+ if (n <= 0) {
+ return;
+ }
+ for (nLeft = n; nLeft > 0; nLeft -= PS_MAXPATH) {
+ int length;
+
+ length = MIN(PS_MAXPATH, nLeft);
+ Blt_Ps_PolylineFromXPoints(ps, points, length);
+ Blt_Ps_Append(ps, "DashesProc stroke\n");
+ points += length;
+ }
+}
+
+void
+Blt_Ps_DrawPolyline(Blt_Ps ps, Point2d *points, int nPoints)
+{
+ int nLeft;
+
+ if (nPoints <= 0) {
+ return;
+ }
+ for (nLeft = nPoints; nLeft > 0; nLeft -= PS_MAXPATH) {
+ int length;
+
+ length = MIN(PS_MAXPATH, nLeft);
+ Blt_Ps_Polyline(ps, points, length);
+ Blt_Ps_Append(ps, "DashesProc stroke\n");
+ points += length;
+ }
+}
+
+void
+Blt_Ps_DrawBitmap(
+ Blt_Ps ps,
+ Display *display,
+ Pixmap bitmap, /* Bitmap to be converted to PostScript */
+ double xScale, double yScale)
+{
+ int width, height;
+ double sw, sh;
+
+ Tk_SizeOfBitmap(display, bitmap, &width, &height);
+ sw = (double)width * xScale;
+ sh = (double)height * yScale;
+ Blt_Ps_Append(ps, " gsave\n");
+ Blt_Ps_Format(ps, " %g %g translate\n", sw * -0.5, sh * 0.5);
+ Blt_Ps_Format(ps, " %g %g scale\n", sw, -sh);
+ Blt_Ps_Format(ps, " %d %d true [%d 0 0 %d 0 %d] {",
+ width, height, width, -height, height);
+ Blt_Ps_XSetBitmapData(ps, display, bitmap, width, height);
+ Blt_Ps_Append(ps, " } imagemask\n grestore\n");
+}
+
+void
+Blt_Ps_Draw2DSegments(Blt_Ps ps, Segment2d *segments, int nSegments)
+{
+ Segment2d *sp, *send;
+
+ Blt_Ps_Append(ps, "newpath\n");
+ for (sp = segments, send = sp + nSegments; sp < send; sp++) {
+ Blt_Ps_Format(ps, " %g %g moveto %g %g lineto\n",
+ sp->p.x, sp->p.y, sp->q.x, sp->q.y);
+ Blt_Ps_Append(ps, "DashesProc stroke\n");
+ }
+}
+
+void
+Blt_Ps_FontName(const char *family, int flags, Tcl_DString *resultPtr)
+{
+ const char *familyName, *weightName, *slantName;
+ int len;
+
+ len = Tcl_DStringLength(resultPtr);
+
+ familyName = FamilyToPsFamily(family);
+ if (familyName == NULL) {
+ Tcl_UniChar ch;
+ char *src, *dest;
+ int upper;
+
+ /*
+ * Inline, capitalize the first letter of each word, lowercase the
+ * rest of the letters in each word, and then take out the spaces
+ * between the words. This may make the DString shorter, which is
+ * safe to do.
+ */
+ Tcl_DStringAppend(resultPtr, family, -1);
+ src = dest = Tcl_DStringValue(resultPtr) + len;
+ upper = TRUE;
+ while (*src != '\0') {
+ while (isspace(*src)) { /* INTL: ISO space */
+ src++;
+ upper = TRUE;
+ }
+ src += Tcl_UtfToUniChar(src, &ch);
+ if (upper) {
+ ch = Tcl_UniCharToUpper(ch);
+ upper = FALSE;
+ } else {
+ ch = Tcl_UniCharToLower(ch);
+ }
+ dest += Tcl_UniCharToUtf(ch, dest);
+ }
+ *dest = '\0';
+ Tcl_DStringSetLength(resultPtr, dest - Tcl_DStringValue(resultPtr));
+ familyName = Tcl_DStringValue(resultPtr) + len;
+ }
+ if (familyName != Tcl_DStringValue(resultPtr) + len) {
+ Tcl_DStringAppend(resultPtr, familyName, -1);
+ familyName = Tcl_DStringValue(resultPtr) + len;
+ }
+ if (strcasecmp(familyName, "NewCenturySchoolbook") == 0) {
+ Tcl_DStringSetLength(resultPtr, len);
+ Tcl_DStringAppend(resultPtr, "NewCenturySchlbk", -1);
+ familyName = Tcl_DStringValue(resultPtr) + len;
+ }
+
+ /* Get the string to use for the weight. */
+ weightName = NULL;
+ if (flags & FONT_BOLD) {
+ if ((strcmp(familyName, "Bookman") == 0) ||
+ (strcmp(familyName, "AvantGarde") == 0)) {
+ weightName = "Demi";
+ } else {
+ weightName = "Bold";
+ }
+ } else {
+ if (strcmp(familyName, "Bookman") == 0) {
+ weightName = "Light";
+ } else if (strcmp(familyName, "AvantGarde") == 0) {
+ weightName = "Book";
+ } else if (strcmp(familyName, "ZapfChancery") == 0) {
+ weightName = "Medium";
+ }
+ }
+
+ /* Get the string to use for the slant. */
+ slantName = NULL;
+ if (flags & FONT_ITALIC) {
+ if ((strcmp(familyName, "Helvetica") == 0) ||
+ (strcmp(familyName, "Courier") == 0) ||
+ (strcmp(familyName, "AvantGarde") == 0)) {
+ slantName = "Oblique";
+ } else {
+ slantName = "Italic";
+ }
+ }
+
+ /*
+ * The string "Roman" needs to be added to some fonts that are not bold
+ * and not italic.
+ */
+ if ((slantName == NULL) && (weightName == NULL)) {
+ if ((strcmp(familyName, "Times") == 0) ||
+ (strcmp(familyName, "NewCenturySchlbk") == 0) ||
+ (strcmp(familyName, "Palatino") == 0)) {
+ Tcl_DStringAppend(resultPtr, "-Roman", -1);
+ }
+ } else {
+ Tcl_DStringAppend(resultPtr, "-", -1);
+ if (weightName != NULL) {
+ Tcl_DStringAppend(resultPtr, weightName, -1);
+ }
+ if (slantName != NULL) {
+ Tcl_DStringAppend(resultPtr, slantName, -1);
+ }
+ }
+}
diff --git a/tlt3.0/bltPs.h b/tlt3.0/bltPs.h
new file mode 100644
index 0000000..93e73ec
--- /dev/null
+++ b/tlt3.0/bltPs.h
@@ -0,0 +1,210 @@
+
+/*
+ * bltPs.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_PS_H
+#define _BLT_PS_H
+
+/*
+ * PageSetup --
+ *
+ * Structure contains information specific to the layout of the page for
+ * printing the graph.
+ *
+ */
+typedef struct {
+ /* User configurable fields */
+
+ int reqWidth, reqHeight; /* If greater than zero, represents the
+ * requested dimensions of the printed graph */
+ int reqPaperWidth;
+ int reqPaperHeight; /* Requested dimensions for the PostScript
+ * page. Can constrain the size of the graph
+ * if the graph (plus padding) is larger than
+ * the size of the page. */
+ Blt_Pad xPad, yPad; /* Requested padding on the exterior of the
+ * graph. This forms the bounding box for
+ * the page. */
+ const char *colorVarName; /* If non-NULL, is the name of a TCL array
+ * variable containing X to output device color
+ * translations */
+ const char *fontVarName; /* If non-NULL, is the name of a TCL array
+ * variable containing X to output device font
+ * translations */
+ int level; /* PostScript Language level 1-3 */
+ unsigned int flags;
+
+ const char **comments; /* User supplied comments to be added. */
+
+ /* Computed fields */
+
+ short int left, bottom; /* Bounding box of the plot in the page. */
+ short int right, top;
+
+ float scale; /* Scale of page. Set if "-maxpect" option
+ * is set, otherwise 1.0. */
+
+ int paperHeight;
+ int paperWidth;
+
+} PageSetup;
+
+#define PS_GREYSCALE (1<<0)
+#define PS_LANDSCAPE (1<<2)
+#define PS_CENTER (1<<3)
+#define PS_MAXPECT (1<<4)
+#define PS_DECORATIONS (1<<5)
+#define PS_FOOTER (1<<6)
+#define PS_FMT_NONE 0
+#define PS_FMT_MASK (PS_FMT_WMF|PS_FMT_EPSI|PS_FMT_TIFF)
+#define PS_FMT_WMF (1<<8)
+#define PS_FMT_EPSI (1<<9)
+#define PS_FMT_TIFF (1<<10)
+
+typedef struct _Blt_Ps *Blt_Ps;
+
+extern Blt_Ps Blt_Ps_Create(Tcl_Interp *interp, PageSetup *setupPtr);
+
+extern void Blt_Ps_Free(Blt_Ps ps);
+
+extern const char *Blt_Ps_GetValue(Blt_Ps ps, int *lengthPtr);
+
+extern Tcl_Interp *Blt_Ps_GetInterp(Blt_Ps ps);
+
+extern Tcl_DString *Blt_Ps_GetDString(Blt_Ps ps);
+
+extern char *Blt_Ps_GetScratchBuffer(Blt_Ps ps);
+
+extern void Blt_Ps_SetInterp(Blt_Ps ps, Tcl_Interp *interp);
+
+extern void Blt_Ps_Append(Blt_Ps ps, const char *string);
+
+extern void Blt_Ps_AppendBytes(Blt_Ps ps, const char *string, int nBytes);
+
+extern void Blt_Ps_VarAppend TCL_VARARGS(Blt_Ps, ps);
+
+extern void Blt_Ps_Format TCL_VARARGS(Blt_Ps, ps);
+
+extern void Blt_Ps_SetClearBackground(Blt_Ps ps);
+
+extern int Blt_Ps_IncludeFile(Tcl_Interp *interp, Blt_Ps ps,
+ const char *fileName);
+
+extern int Blt_Ps_GetPicaFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ int *picaPtr);
+
+extern int Blt_Ps_GetPadFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Blt_Pad *padPtr);
+
+extern int Blt_Ps_ComputeBoundingBox(PageSetup *setupPtr, int w, int h);
+
+extern void Blt_Ps_Rectangle(Blt_Ps ps, int x, int y, int w, int h);
+
+
+extern int Blt_Ps_SaveFile(Tcl_Interp *interp, Blt_Ps ps,
+ const char *fileName);
+
+#ifdef _TK
+
+#include "bltFont.h"
+#include "bltText.h"
+
+extern void Blt_Ps_XSetLineWidth(Blt_Ps ps, int lineWidth);
+
+extern void Blt_Ps_XSetBackground(Blt_Ps ps, XColor *colorPtr);
+
+extern void Blt_Ps_XSetBitmapData(Blt_Ps ps, Display *display,
+ Pixmap bitmap, int width, int height);
+
+extern void Blt_Ps_XSetForeground(Blt_Ps ps, XColor *colorPtr);
+
+extern void Blt_Ps_XSetFont(Blt_Ps ps, Blt_Font font);
+
+extern void Blt_Ps_XSetDashes(Blt_Ps ps, Blt_Dashes *dashesPtr);
+
+extern void Blt_Ps_XSetLineAttributes(Blt_Ps ps, XColor *colorPtr,
+ int lineWidth, Blt_Dashes *dashesPtr, int capStyle, int joinStyle);
+
+extern void Blt_Ps_XSetStipple(Blt_Ps ps, Display *display, Pixmap bitmap);
+
+extern void Blt_Ps_Polyline(Blt_Ps ps, Point2d *screenPts, int nScreenPts);
+
+extern void Blt_Ps_XDrawLines(Blt_Ps ps, XPoint *points, int n);
+
+extern void Blt_Ps_XDrawSegments(Blt_Ps ps, XSegment *segments,
+ int nSegments);
+
+extern void Blt_Ps_DrawPolyline(Blt_Ps ps, Point2d *points, int n);
+
+extern void Blt_Ps_Draw2DSegments(Blt_Ps ps, Segment2d *segments,
+ int nSegments);
+
+extern void Blt_Ps_Draw3DRectangle(Blt_Ps ps, Tk_3DBorder border,
+ double x, double y, int width, int height, int borderWidth, int relief);
+
+extern void Blt_Ps_Fill3DRectangle(Blt_Ps ps, Tk_3DBorder border, double x,
+ double y, int width, int height, int borderWidth, int relief);
+
+extern void Blt_Ps_XFillRectangle(Blt_Ps ps, double x, double y,
+ int width, int height);
+
+extern void Blt_Ps_XFillRectangles(Blt_Ps ps, XRectangle *rects, int n);
+
+extern void Blt_Ps_XFillPolygon(Blt_Ps ps, Point2d *screenPts,
+ int nScreenPts);
+
+extern void Blt_Ps_DrawPhoto(Blt_Ps ps, Tk_PhotoHandle photoToken,
+ double x, double y);
+
+extern void Blt_Ps_XDrawWindow(Blt_Ps ps, Tk_Window tkwin,
+ double x, double y);
+
+extern void Blt_Ps_DrawText(Blt_Ps ps, const char *string,
+ TextStyle *attrPtr, double x, double y);
+
+extern void Blt_Ps_DrawBitmap(Blt_Ps ps, Display *display, Pixmap bitmap,
+ double scaleX, double scaleY);
+
+extern void Blt_Ps_XSetCapStyle(Blt_Ps ps, int capStyle);
+
+extern void Blt_Ps_XSetJoinStyle(Blt_Ps ps, int joinStyle);
+
+extern void Blt_Ps_PolylineFromXPoints(Blt_Ps ps, XPoint *points, int n);
+
+extern void Blt_Ps_Polygon(Blt_Ps ps, Point2d *screenPts, int nScreenPts);
+
+extern void Blt_Ps_SetPrinting(Blt_Ps ps, int value);
+extern int Blt_Ps_IsPrinting(void);
+
+extern int Blt_Ps_TextWidth(Blt_Font font, const char *string, int nBytes);
+
+extern int Blt_Ps_GetFontMetrics(Blt_Font font, Blt_FontMetrics *fmPtr);
+
+extern void Blt_Ps_FontName(const char *family, int flags,
+ Tcl_DString *resultPtr);
+
+#endif /* _TK */
+
+#endif /* BLT_PS_H */
diff --git a/tlt3.0/bltPsAfm.c b/tlt3.0/bltPsAfm.c
new file mode 100644
index 0000000..59f38b4
--- /dev/null
+++ b/tlt3.0/bltPsAfm.c
@@ -0,0 +1,1557 @@
+/*
+ * bltPsAfm.c --
+ *
+ * This module implements an Adobe Font Metric File parser for the purpose of
+ * determining font metrics when generating PostScript.
+ *
+ * Copyright 2009 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+
+#include "bltInt.h"
+#include "bltHash.h"
+#include "bltPs.h"
+#include "bltOp.h"
+#include "bltText.h"
+#include "bltFont.h"
+
+#define AFM_MAXSTATES 50
+#define AFM_MAXLINE 512
+#define FM(x) Blt_Offset(AdobeFontMetrics, x)
+#define CM(x) Blt_Offset(CharMetrics, x)
+#define FTOA(x) Blt_Dtoa(interp, (double)x)
+
+typedef struct {
+ const char *name;
+ short int code;
+} Symbol;
+
+static Symbol isoLatin1Symbols[] = {
+ { "A", 65 },
+ { "AE", 198 },
+ { "Aacute", 193 },
+ { "Acircumflex", 194 },
+ { "Adieresis", 196 },
+ { "Agrave", 192 },
+ { "Aring", 197 },
+ { "Atilde", 195 },
+ { "B", 66 },
+ { "C", 67 },
+ { "Ccedilla", 199 },
+ { "D", 68 },
+ { "E", 69 },
+ { "Eacute", 201 },
+ { "Ecircumflex", 202 },
+ { "Edieresis", 203 },
+ { "Egrave", 200 },
+ { "Eth", 208 },
+ { "F", 70 },
+ { "G", 71 },
+ { "H", 72 },
+ { "I", 73 },
+ { "Iacute", 205 },
+ { "Icircumflex", 206 },
+ { "Idieresis", 207 },
+ { "Igrave", 204 },
+ { "J", 74 },
+ { "K", 75 },
+ { "L", 76 },
+ { "M", 77 },
+ { "N", 78 },
+ { "Ntilde", 209 },
+ { "O", 79 },
+ { "Oacute", 211 },
+ { "Ocircumflex", 212 },
+ { "Odieresis", 214 },
+ { "Ograve", 210 },
+ { "Oslash", 216 },
+ { "Otilde", 213 },
+ { "P", 80 },
+ { "Q", 81 },
+ { "R", 82 },
+ { "S", 83 },
+ { "T", 84 },
+ { "Thorn", 222 },
+ { "U", 85 },
+ { "Uacute", 218 },
+ { "Ucircumflex", 219 },
+ { "Udieresis", 220 },
+ { "Ugrave", 217 },
+ { "V", 86 },
+ { "W", 87 },
+ { "X", 88 },
+ { "Y", 89 },
+ { "Yacute", 221 },
+ { "Z", 90 },
+ { "a", 97 },
+ { "aacute", 225 },
+ { "acircumflex", 226 },
+ { "acute", 180 },
+ { "adieresis", 228 },
+ { "ae", 230 },
+ { "agrave", 224 },
+ { "ampersand", 38 },
+ { "aring", 229 },
+ { "asciicircum", 94 },
+ { "asciitilde", 126 },
+ { "asterisk", 42 },
+ { "at", 64 },
+ { "atilde", 227 },
+ { "b", 98 },
+ { "backslash", 92 },
+ { "bar", 124 },
+ { "braceleft", 123 },
+ { "braceright", 125 },
+ { "bracketleft", 91 },
+ { "bracketright", 93 },
+ { "brokenbar", 166 },
+ { "florin", 166 },
+ { "c", 99 },
+ { "ccedilla", 231 },
+ { "cedilla", 184 },
+ { "cent", 162 },
+ { "colon", 58 },
+ { "comma", 44 },
+ { "controlACK", 6 },
+ { "controlBEL", 7 },
+ { "controlBS", 8 },
+ { "controlCAN", 24 },
+ { "controlCR", 13 },
+ { "controlDC1", 17 },
+ { "controlDC2", 18 },
+ { "controlDC3", 19 },
+ { "controlDC4", 20 },
+ { "controlDEL", 127 },
+ { "controlDLE", 16 },
+ { "controlEM", 25 },
+ { "controlENQ", 5 },
+ { "controlEOT", 4 },
+ { "controlESC", 27 },
+ { "controlETB", 23 },
+ { "controlETX", 3 },
+ { "controlFF", 12 },
+ { "controlFS", 28 },
+ { "controlGS", 29 },
+ { "controlHT", 9 },
+ { "controlLF", 10 },
+ { "controlNAK", 21 },
+ { "controlRS", 30 },
+ { "controlSI", 15 },
+ { "controlSO", 14 },
+ { "controlSOT", 2 },
+ { "controlSTX", 1 },
+ { "controlSUB", 26 },
+ { "controlSYN", 22 },
+ { "controlUS", 31 },
+ { "controlVT", 11 },
+ { "copyright", 169 },
+ { "currency", 164 },
+ { "fraction", 164 },
+ { "d", 100 },
+ { "degree", 176 },
+ { "dieresis", 168 },
+ { "divide", 247 },
+ { "dollar", 36 },
+ { "e", 101 },
+ { "eacute", 233 },
+ { "ecircumflex", 234 },
+ { "edieresis", 235 },
+ { "egrave", 232 },
+ { "eight", 56 },
+ { "equal", 61 },
+ { "eth", 240 },
+ { "exclam", 33 },
+ { "exclamdown", 161 },
+ { "f", 102 },
+ { "five", 53 },
+ { "four", 52 },
+ { "g", 103 },
+ { "germandbls", 223 },
+ { "grave", 96 },
+ { "quoteleft", 96 },
+ { "greater", 62 },
+ { "guillemotleft", 171 },
+ { "guillemotright", 187 },
+ { "h", 104 },
+ { "hyphen", 45 },
+ { "i", 105 },
+ { "iacute", 237 },
+ { "icircumflex", 238 },
+ { "idieresis", 239 },
+ { "igrave", 236 },
+ { "j", 106 },
+ { "k", 107 },
+ { "l", 108 },
+ { "less", 60 },
+ { "logicalnot", 172 },
+ { "m", 109 },
+ { "macron", 175 },
+ { "middot", 183 },
+ { "mu", 181 },
+ { "mu1", 181 },
+ { "multiply", 215 },
+ { "n", 110 },
+ { "nbspace", 160 },
+ { "nine", 57 },
+ { "nonbreakingspace", 160 },
+ { "ntilde", 241 },
+ { "numbersign", 35 },
+ { "o", 111 },
+ { "oacute", 243 },
+ { "ocircumflex", 244 },
+ { "odieresis", 246 },
+ { "ograve", 242 },
+ { "one", 49 },
+ { "onehalf", 189 },
+ { "onequarter", 188 },
+ { "onesuperior", 185 },
+ { "ordfeminine", 170 },
+ { "ordmasculine", 186 },
+ { "oslash", 248 },
+ { "otilde", 245 },
+ { "overscore", 175 },
+ { "p", 112 },
+ { "paragraph", 182 },
+ { "parenleft", 40 },
+ { "parenright", 41 },
+ { "percent", 37 },
+ { "period", 46 },
+ { "periodcentered", 183 },
+ { "plus", 43 },
+ { "plusminus", 177 },
+ { "q", 113 },
+ { "question", 63 },
+ { "questiondown", 191 },
+ { "quotedbl", 34 },
+ { "quotesingle", 39 },
+ { "quoteright", 39 },
+ { "r", 114 },
+ { "registered", 174 },
+ { "s", 115 },
+ { "section", 167 },
+ { "semicolon", 59 },
+ { "seven", 55 },
+ { "sfthyphen", 173 },
+ { "six", 54 },
+ { "slash", 47 },
+ { "softhyphen", 173 },
+ { "space", 32 },
+ { "spacehackarabic", 32 },
+ { "sterling", 163 },
+ { "t", 116 },
+ { "thorn", 254 },
+ { "three", 51 },
+ { "threequarters", 190 },
+ { "threesuperior", 179 },
+ { "two", 50 },
+ { "twosuperior", 178 },
+ { "u", 117 },
+ { "uacute", 250 },
+ { "ucircumflex", 251 },
+ { "udieresis", 252 },
+ { "ugrave", 249 },
+ { "underscore", 95 },
+ { "v", 118 },
+ { "verticalbar", 124 },
+ { "w", 119 },
+ { "x", 120 },
+ { "y", 121 },
+ { "yacute", 253 },
+ { "ydieresis", 255 },
+ { "yen", 165 },
+ { "z", 122 },
+ { "zero", 48 },
+ { NULL, -1 }
+};
+
+typedef struct _Parser Parser;
+
+typedef int (ParseProc) (Parser *parserPtr, char *record, int offset);
+
+typedef struct {
+ const char *key;
+ unsigned int nArgs;
+ ParseProc *proc;
+ size_t offset;
+} ParserSpec;
+
+typedef struct {
+ float llx, lly, urx, ury;
+} CharBBox;
+
+typedef struct {
+ float x, y;
+} Point;
+
+typedef struct {
+ short int first, second;
+} LigatureKey;
+
+typedef struct {
+ const char *successor;
+ const char *ligature;
+ short int index;
+} Ligature;
+
+typedef struct {
+ CharBBox bbox;
+ int index;
+ const char *name;
+ int hasLigature;
+ int hasKernPair;
+ Point w;
+ Point vVector;
+} CharMetrics;
+
+typedef struct {
+ float x, y;
+ short int first, second;
+} KernPairs;
+
+typedef struct {
+ short int first, second;
+} KernPairsKey;
+
+typedef struct {
+ float degree;
+ float minPointSize, maxPointSize;
+ float minKern, maxKern;
+} TrackKern;
+
+typedef struct {
+ const char *afmVersion;
+ const char *familyName;
+ const char *fontName;
+ const char *fullName;
+ const char *weight;
+ const char *comment;
+ const char *copyright;
+ const char *notice;
+ float italicAngle;
+ CharBBox fontBBox;
+ float underlinePosition;
+ float underlineThickness;
+ const char *characterSet;
+ int characters;
+ const char *version;
+ const char *encodingScheme;
+ float capHeight;
+ float xHeight;
+ float ascender, descender;
+ int metricSets;
+ Point charWidth;
+ int escChar;
+ int isFixedPitch;
+ int isBaseFont;
+ int isCIDFont;
+ int isFixedV;
+ int mappingScheme;
+ int nCharMetrics;
+ int nComposites;
+ int nDirection;
+ int nKernPairs;
+ int nTrackKern;
+
+ float stdHW, stdVW;
+ Point vVector;
+ TrackKern *trackKern;
+
+ KernPairs *kernPairs;
+ CharMetrics metrics[256];
+ Blt_HashTable metricsTable;
+ Blt_HashTable kernPairsTable;
+ Blt_HashTable ligatureTable;
+ Blt_HashTable symbolTable;
+ int refCount;
+ Blt_HashEntry *hashPtr;
+ float pointSize; /* Current point size of font. */
+} AdobeFontMetrics;
+
+struct _Parser {
+ Tcl_Channel channel; /* Channel to AdobeFontMetrics file. */
+ AdobeFontMetrics *afmPtr;
+ jmp_buf jmpbuf;
+ Tcl_DString errors; /* Contains error message. */
+ int nErrors;
+ int argc; /* # arguments (word) of last line. */
+ const char **argv; /* Split of last line. */
+ Tcl_DString lastLine; /* Contains last line read from file. */
+ int lineNumber;
+};
+
+static Blt_HashTable fontTable;
+static int initialized;
+
+static int ParseLine(Parser *parserPtr, ParserSpec *specs, int nSpecs,
+ ClientData clientData);
+
+static INLINE int
+Points(AdobeFontMetrics *afmPtr, double x)
+{
+ return (int)round((afmPtr->pointSize * x) / 1000.0);
+}
+
+/*ARGSUSED*/
+static void
+ParserError TCL_VARARGS_DEF(Parser *, arg1)
+{
+ Parser *parserPtr;
+ const char *fmt;
+ char string[BUFSIZ+4];
+ int length;
+ va_list args;
+
+ parserPtr = TCL_VARARGS_START(Parser *, arg1, args);
+ fmt = va_arg(args, char *);
+ length = vsnprintf(string, BUFSIZ, fmt, args);
+ if (length > BUFSIZ) {
+ strcat(string, "...");
+ }
+ Tcl_DStringAppend(&parserPtr->errors, "line ", 5);
+ Tcl_DStringAppend(&parserPtr->errors, Blt_Itoa(parserPtr->lineNumber), -1);
+ Tcl_DStringAppend(&parserPtr->errors, ": ", 2);
+ Tcl_DStringAppend(&parserPtr->errors, string, -1);
+ Tcl_DStringAppend(&parserPtr->errors, "\n", -1);
+ va_end(args);
+ longjmp(parserPtr->jmpbuf, 0);
+}
+
+static int
+GetNumber(Parser *parserPtr, const char *string, float *valuePtr)
+{
+ char *end;
+ double d;
+
+ errno = 0;
+ d = strtod(string, &end); /* INTL: Tcl source. */
+ if (end == string) {
+ badDouble:
+ ParserError(parserPtr, "expected floating-point number but got \"%s\"",
+ string);
+ }
+ if (errno != 0 && (d == HUGE_VAL || d == -HUGE_VAL || d == 0)) {
+ ParserError(parserPtr, "number \"%s\" is too big to represent",
+ string);
+ }
+ while ((*end != 0) && isspace((unsigned char)(*end))) { /* INTL: ISO space. */
+ end++;
+ }
+ if (*end != 0) {
+ goto badDouble;
+ }
+ *valuePtr = (float)d;
+ return TCL_OK;
+}
+
+static int
+GetHexNumber(Parser *parserPtr, const char *string, int *valuePtr)
+{
+ char *p;
+ int value;
+
+ if (*string == '<') {
+ string++;
+ }
+ value = strtoul(string, &p, 8);
+ if ((p == string) || (*p != '>')) {
+ ParserError(parserPtr, "expected hex number but got \"%s\"", string);
+ }
+ *valuePtr = value;
+ return TCL_OK;
+}
+
+static int
+GetLine(Parser *parserPtr)
+{
+ Tcl_DStringSetLength(&parserPtr->lastLine, 0);
+ while (!Tcl_Eof(parserPtr->channel)) {
+ const char *p;
+ int code;
+
+ code = Tcl_Gets(parserPtr->channel, &parserPtr->lastLine);
+ if (code < 0) {
+ if (Tcl_Eof(parserPtr->channel)) {
+ return TCL_RETURN;
+ }
+ ParserError(parserPtr, "error reading channel: %s\n",
+ strerror(errno));
+ }
+ parserPtr->lineNumber++;
+ for (p = Tcl_DStringValue(&parserPtr->lastLine); isspace(*p); p++) {
+ /* skip blanks */
+ }
+ if (*p == '\0') {
+ continue;
+ }
+ return TCL_OK;
+ }
+ return TCL_RETURN;
+}
+
+static void
+SplitLine(Parser *parserPtr, const char *line)
+{
+ const char *p;
+ int count;
+ size_t strSize, addrSize;
+
+ if (parserPtr->argv != NULL) {
+ free((char *)parserPtr->argv);
+ parserPtr->argv = NULL;
+ parserPtr->argc = 0;
+ }
+ /* Count the # of arguments to determine what size array to allocate. */
+ count = 0;
+ p = line;
+ while (*p != '\0') {
+ while (isspace(*p)) p++; /* Skip whitespace. */
+ if (*p == '\0') {
+ break;
+ }
+ while (!isspace(*p) && (*p != '\0')) p++; /* Skip the word itself. */
+ count++;
+ }
+ if (count == 0) {
+ return; /* No arguments. */
+ }
+ addrSize = sizeof(char **) * (count + 1);
+ strSize = p - line + 1;
+ {
+ char *buffer, *p;
+ const char **array;
+
+ buffer = malloc(addrSize + strSize);
+ assert(buffer);
+ p = buffer + addrSize;
+ strcpy(p, line); /* Copy the string into the buffer. */
+ array = (const char **)buffer;
+ count = 0;
+ while (*p != '\0') {
+ while (isspace(*p)) {
+ *p++ = '\0'; /* Convert whitespace to NULs. */
+ }
+ if (*p == '\0') {
+ break;
+ }
+ array[count] = p;
+ while (!isspace(*p) && (*p != '\0')) p++;
+ count++;
+ }
+ array[count] = NULL;
+ parserPtr->argv = array;
+ parserPtr->argc = count;
+ }
+}
+
+static int
+SplitNextLine(Parser *parserPtr)
+{
+ int result;
+
+ if (parserPtr->argv != NULL) {
+ free((char *)parserPtr->argv);
+ parserPtr->argv = NULL;
+ parserPtr->argc = 0;
+ }
+ result = GetLine(parserPtr);
+ if (result == TCL_OK) {
+ SplitLine(parserPtr, Tcl_DStringValue(&parserPtr->lastLine));
+ return TCL_OK;
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LookupKeyword --
+ *
+ *---------------------------------------------------------------------------
+ */
+static ParserSpec *
+LookupKeyword(ParserSpec *specs, int nSpecs, const char *string)
+{
+ char c;
+ int high, low;
+
+ low = 0;
+ high = nSpecs - 1;
+ c = string[0];
+ while (low <= high) {
+ ParserSpec *specPtr;
+ int compare;
+ int median;
+
+ median = (low + high) >> 1;
+ specPtr = specs + median;
+
+ /* Test the first character */
+ compare = c - specPtr->key[0];
+ if (compare == 0) {
+ /* Now test the entire string */
+ compare = strcmp(string, specPtr->key);
+ }
+ if (compare < 0) {
+ high = median - 1;
+ } else if (compare > 0) {
+ low = median + 1;
+ } else {
+ return specPtr;
+ }
+ }
+ return NULL; /* Can't find operation */
+}
+
+static int
+ParseLine(Parser *parserPtr, ParserSpec *specs, int nSpecs,
+ ClientData clientData)
+{
+ ParserSpec *specPtr;
+
+ specPtr = LookupKeyword(specs, nSpecs, parserPtr->argv[0]);
+ if (specPtr == NULL) {
+ ParserError(parserPtr, "unknown keyword \"%s\"", parserPtr->argv[0]);
+ }
+ if ((specPtr->nArgs > 0) && (specPtr->nArgs != parserPtr->argc)) {
+ ParserError(parserPtr, "wrong # arguments for \"%s\"", specPtr->key);
+ }
+ if (specPtr->proc == NULL) {
+ return TCL_OK;
+ }
+ return (*specPtr->proc)(parserPtr, clientData, specPtr->offset);
+}
+
+static int
+ParseEndSection(Parser *parserPtr, char *record, int offset)
+{
+ return TCL_CONTINUE; /* Indicates end of section. */
+}
+
+static long
+LookupSymbol(AdobeFontMetrics *afmPtr, const char *symbol)
+{
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&afmPtr->symbolTable, symbol);
+ if (hPtr != NULL) {
+ return (long)Blt_GetHashValue(hPtr);
+ }
+ /*fprintf(stderr, "unknown symbol \"%s\"\n", symbol);*/
+ return -1;
+}
+
+static void
+InitSymbolTable(AdobeFontMetrics *afmPtr)
+{
+ Symbol *symPtr;
+
+ Blt_InitHashTable(&afmPtr->symbolTable, BLT_STRING_KEYS);
+ for (symPtr = isoLatin1Symbols; symPtr->name != NULL; symPtr++) {
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&afmPtr->symbolTable, symPtr->name, &isNew);
+ Blt_SetHashValue(hPtr, (ClientData)(long)symPtr->code);
+ }
+}
+
+static void
+UpdateSymbol(AdobeFontMetrics *afmPtr, long code, const char *symbol)
+{
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&afmPtr->symbolTable, symbol, &isNew);
+ Blt_SetHashValue(hPtr, (ClientData)code);
+}
+
+static void
+BuildKernPairsTable(AdobeFontMetrics *afmPtr)
+{
+ KernPairs *kp, *kend;
+
+ Blt_InitHashTable(&afmPtr->kernPairsTable,
+ sizeof(KernPairsKey) / sizeof(int));
+ for (kp = afmPtr->kernPairs, kend = kp + afmPtr->nKernPairs; kp < kend;
+ kp++) {
+ KernPairsKey key;
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ memset(&key, 0, sizeof(key));
+ key.first = kp->first;
+ key.second = kp->second;
+ hPtr = Blt_CreateHashEntry(&afmPtr->kernPairsTable, (char *)&key,
+ &isNew);
+ Blt_SetHashValue(hPtr, (ClientData)kp);
+ }
+}
+
+static KernPairs *
+GetKernPairs(AdobeFontMetrics *afmPtr, int c1, int c2)
+{
+ KernPairsKey key;
+ Blt_HashEntry *hPtr;
+
+ key.first = c1;
+ key.second = c2;
+
+ hPtr = Blt_FindHashEntry(&afmPtr->kernPairsTable, (char *)&key);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Blt_GetHashValue(hPtr);
+}
+
+static Parser *
+NewParser(AdobeFontMetrics *afmPtr, const char *fileName)
+{
+ Parser *parserPtr;
+ Tcl_Channel channel;
+
+ channel = Tcl_OpenFileChannel(NULL, fileName, "r", 0);
+ if (channel == NULL) {
+ fprintf(stderr, "can't open %s\n", fileName);
+ return NULL;
+ }
+ if ((Tcl_SetChannelOption(NULL, channel, "-translation","auto")!=TCL_OK)||
+ (Tcl_SetChannelOption(NULL, channel, "-eofchar", "\x1a") != TCL_OK)) {
+ return NULL;
+ }
+ parserPtr = calloc(1, sizeof(Parser));
+ assert(parserPtr);
+ parserPtr->channel = channel;
+ parserPtr->afmPtr = afmPtr;
+ InitSymbolTable(afmPtr);
+ Tcl_DStringInit(&parserPtr->errors);
+ Tcl_DStringAppend(&parserPtr->errors, "error reading \"", -1);
+ Tcl_DStringAppend(&parserPtr->errors, fileName, -1);
+ Tcl_DStringAppend(&parserPtr->errors, "\": ", -1);
+ Tcl_DStringInit(&parserPtr->lastLine);
+ return parserPtr;
+}
+
+static void
+DestroyParser(Parser *parserPtr)
+{
+ if (parserPtr->argv != NULL) {
+ free((char *)parserPtr->argv);
+ }
+ Tcl_Close(NULL, parserPtr->channel);
+ Tcl_DStringFree(&parserPtr->errors);
+ Tcl_DStringFree(&parserPtr->lastLine);
+ free(parserPtr);
+}
+
+static void
+DestroyAdobeFontMetrics(AdobeFontMetrics *afmPtr)
+{
+ if (afmPtr->afmVersion != NULL) {
+ free((char *)afmPtr->afmVersion);
+ }
+ if (afmPtr->characterSet != NULL) {
+ free((char *)afmPtr->characterSet);
+ }
+ if (afmPtr->comment != NULL) {
+ free((char *)afmPtr->comment);
+ }
+ if (afmPtr->copyright != NULL) {
+ free((char *)afmPtr->copyright);
+ }
+ if (afmPtr->encodingScheme != NULL) {
+ free((char *)afmPtr->encodingScheme);
+ }
+ if (afmPtr->familyName != NULL) {
+ free((char *)afmPtr->familyName);
+ }
+ if (afmPtr->fontName != NULL) {
+ free((char *)afmPtr->fontName);
+ }
+ if (afmPtr->fullName != NULL) {
+ free((char *)afmPtr->fullName);
+ }
+ if (afmPtr->notice != NULL) {
+ free((char *)afmPtr->notice);
+ }
+ if (afmPtr->version != NULL) {
+ free((char *)afmPtr->version);
+ }
+ if (afmPtr->weight != NULL) {
+ free((char *)afmPtr->weight);
+ }
+ if (afmPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&fontTable, afmPtr->hashPtr);
+ }
+ Blt_DeleteHashTable(&afmPtr->kernPairsTable);
+ Blt_DeleteHashTable(&afmPtr->metricsTable);
+ Blt_DeleteHashTable(&afmPtr->symbolTable);
+ Blt_DeleteHashTable(&afmPtr->ligatureTable);
+ if (afmPtr->kernPairs != NULL) {
+ free(afmPtr->kernPairs);
+ }
+ if (afmPtr->trackKern != NULL) {
+ free(afmPtr->trackKern);
+ }
+ free((char *)afmPtr);
+}
+
+static int
+ParseInt(Parser *parserPtr, char *record, int offset)
+{
+ int *valuePtr = (int *)(record + offset);
+
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], valuePtr) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer.",
+ parserPtr->argv[1]);
+ }
+ return TCL_OK;
+}
+
+static int
+ParseHex(Parser *parserPtr, char *record, int offset)
+{
+ int *valuePtr = (int *)(record + offset);
+
+ return GetHexNumber(parserPtr, parserPtr->argv[1], valuePtr);
+}
+
+static int
+ParseBoolean(Parser *parserPtr, char *record, int offset)
+{
+ int *valuePtr = (int *)(record + offset);
+
+ if (Tcl_GetBoolean(NULL, parserPtr->argv[1], valuePtr) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to boolean.",
+ parserPtr->argv[1]);
+ }
+ return TCL_OK;
+}
+
+
+static int
+ParseNumber(Parser *parserPtr, char *record, int offset)
+{
+ float *valuePtr = (float *)(record + offset);
+
+ return GetNumber(parserPtr, parserPtr->argv[1], valuePtr);
+}
+
+
+static int
+ParsePoint(Parser *parserPtr, char *record, int offset)
+{
+ Point *pointPtr = (Point *)(record + offset);
+
+ if ((GetNumber(parserPtr, parserPtr->argv[1], &pointPtr->x) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[2], &pointPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static int
+ParseBBox(Parser *parserPtr, char *record, int offset)
+{
+ CharBBox *bboxPtr = (CharBBox *)(record + offset);
+
+ if ((GetNumber(parserPtr, parserPtr->argv[1], &bboxPtr->llx) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[2], &bboxPtr->lly) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[3], &bboxPtr->urx) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[4], &bboxPtr->ury) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static int
+ParseString(Parser *parserPtr, char *record, int offset)
+{
+ char **args = (char **)(record + offset);
+
+ if (*args != NULL) {
+ free(*args);
+ *args = NULL;
+ }
+ *args = Tcl_Merge(parserPtr->argc - 1 , parserPtr->argv + 1);
+ if (*args == NULL) {
+ ParserError(parserPtr, "can't merge \"%s\" string.",
+ parserPtr->argv[0]);
+ }
+ return TCL_OK;
+}
+
+static int
+ParseName(Parser *parserPtr, char *record, int offset)
+{
+ const char **valuePtr = (const char **)(record + offset);
+
+ if (*valuePtr != NULL) {
+ free((char *)*valuePtr);
+ }
+ *valuePtr = Blt_Strdup(parserPtr->argv[1]);
+ return TCL_OK;
+}
+
+
+static int
+ParseStartComposites(Parser *parserPtr, char *record, int offset)
+{
+ int *valuePtr = (int *)(record + offset);
+ int n;
+
+ assert(*valuePtr == 0);
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], &n) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer",
+ parserPtr->argv[1]);
+ }
+ n++;
+ *valuePtr = n;
+ for (;;) {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartComposites");
+ }
+ if (strcmp(parserPtr->argv[0], "EndComposites") == 0) {
+ return TCL_OK;
+ }
+ }
+ /*notreached*/
+ return TCL_ERROR;
+}
+
+
+static ParserSpec directionSpecs[] = {
+ { "CharWidth", 3, ParsePoint, FM(charWidth) },
+ { "EndDirection", 1, ParseEndSection, 0 },
+ { "IsFixedPitch", 2, ParseBoolean, FM(isFixedPitch) },
+ { "ItalicAngle", 2, ParseNumber, FM(italicAngle) },
+ { "UnderlinePosition", 2, ParseNumber, FM(underlinePosition) },
+ { "UnderlineThickness",2, ParseNumber, FM(underlineThickness) }
+};
+static int nDirectionSpecs = sizeof(directionSpecs) / sizeof(ParserSpec);
+
+
+static int
+ParseStartDirection(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ int *valuePtr = (int *)(record + offset);
+ int n;
+ int result;
+
+ assert(*valuePtr == 0);
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], &n) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer.",
+ parserPtr->argv[1]);
+ }
+ do {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartDirection");
+ }
+ result = ParseLine(parserPtr, directionSpecs, nDirectionSpecs, afmPtr);
+ } while (result == TCL_OK);
+ if (result == TCL_CONTINUE) {
+ return TCL_OK; /* Found EndKernPairs */
+ }
+ return TCL_ERROR;
+}
+
+static int
+ParseTrackKern(Parser *parserPtr, char *record, int offset)
+{
+ TrackKern *tp = (TrackKern *)(record + offset);
+
+ if ((GetNumber(parserPtr, parserPtr->argv[1], &tp->degree) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[2], &tp->minPointSize)!=TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[3], &tp->minKern) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[4], &tp->maxPointSize)!=TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[5], &tp->maxKern) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static ParserSpec trackKernSpecs[] = {
+ { "EndTrackKern", 1, ParseEndSection, 0 },
+ { "TrackKern", 6, ParseTrackKern, 0 },
+};
+static int nTrackKernSpecs = sizeof(trackKernSpecs) / sizeof(ParserSpec);
+
+static int
+ParseStartTrackKern(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ TrackKern *tp;
+ int *valuePtr = (int *)(record + offset);
+ int n;
+ int result;
+
+ assert(*valuePtr == 0);
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], &n) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer.",
+ parserPtr->argv[1]);
+ }
+ n++;
+ *valuePtr = n;
+ afmPtr->trackKern = calloc(n, sizeof(TrackKern));
+ assert(afmPtr->trackKern);
+ tp = afmPtr->trackKern;
+ do {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartTrackKern");
+ }
+ result = ParseLine(parserPtr, trackKernSpecs, nTrackKernSpecs, tp);
+ tp++;
+ } while (result == TCL_OK);
+ if (result == TCL_CONTINUE) {
+ assert((tp - afmPtr->trackKern) == n);
+ return TCL_OK; /* Found EndTrackKern */
+ }
+ return TCL_ERROR;
+}
+
+
+static int
+ParseKP(Parser *parserPtr, char *record, int offset)
+{
+ KernPairs *pairPtr = (KernPairs *)(record + offset);
+
+ pairPtr->first = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[1]);
+ pairPtr->second = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[2]);
+ if ((GetNumber(parserPtr, parserPtr->argv[3], &pairPtr->x) != TCL_OK) ||
+ (GetNumber(parserPtr, parserPtr->argv[4], &pairPtr->y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+static int
+ParseKPH(Parser *parserPtr, char *record, int offset)
+{
+ KernPairs *pairPtr = (KernPairs *)(record + offset);
+ int x, y;
+
+ pairPtr->first = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[1]);
+ pairPtr->second = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[2]);
+ if ((GetHexNumber(parserPtr, parserPtr->argv[3], &x) != TCL_OK) ||
+ (GetHexNumber(parserPtr, parserPtr->argv[4], &y) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ pairPtr->x = (float)x;
+ pairPtr->y = (float)y;
+ return TCL_OK;
+}
+
+static int
+ParseKPX(Parser *parserPtr, char *record, int offset)
+{
+ KernPairs *pairPtr = (KernPairs *)(record + offset);
+
+ pairPtr->first = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[1]);
+ pairPtr->second = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[2]);
+ if (GetNumber(parserPtr, parserPtr->argv[3], &pairPtr->x) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pairPtr->y = 0;
+ return TCL_OK;
+}
+
+static int
+ParseKPY(Parser *parserPtr, char *record, int offset)
+{
+ KernPairs *pairPtr = (KernPairs *)(record + offset);
+
+ pairPtr->first = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[1]);
+ pairPtr->second = LookupSymbol(parserPtr->afmPtr, parserPtr->argv[2]);
+ if (GetNumber(parserPtr, parserPtr->argv[3], &pairPtr->y) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ pairPtr->x = 0;
+ return TCL_OK;
+}
+
+static ParserSpec kernPairsSpecs[] = {
+ { "EndKernPairs", 1, ParseEndSection, 0 },
+ { "KP", 5, ParseKP, 0 },
+ { "KPH", 5, ParseKPH, 0 },
+ { "KPX", 4, ParseKPX, 0 },
+ { "KPY", 4, ParseKPY, 0 },
+};
+static int nKernPairsSpecs = sizeof(kernPairsSpecs) / sizeof(ParserSpec);
+
+static int
+ParseStartKernPairs(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ int *valuePtr = (int *)(record + offset);
+ int n;
+ int result;
+ KernPairs *kp;
+
+ assert(*valuePtr == 0);
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], &n) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer.",
+ parserPtr->argv[1]);
+ }
+ n++;
+ *valuePtr = n;
+ afmPtr->kernPairs = calloc(n, sizeof(KernPairs));
+ assert(afmPtr->kernPairs);
+ kp = afmPtr->kernPairs;
+ do {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartKernPairs");
+ }
+ result = ParseLine(parserPtr, kernPairsSpecs, nKernPairsSpecs, kp);
+ kp++;
+ } while (result == TCL_OK);
+ if (result == TCL_CONTINUE) {
+ assert((kp - afmPtr->kernPairs) == *valuePtr);
+ return TCL_OK; /* Found EndKernPairs */
+ }
+ return TCL_ERROR;
+}
+
+
+static ParserSpec kernDataSpecs[] = {
+ { "EndKernData", 1, ParseEndSection, 0 },
+ { "StartKernPairs", 2, ParseStartKernPairs, FM(nKernPairs) },
+ { "StartKernPairs0", 2, ParseStartKernPairs, FM(nKernPairs) },
+ { "StartKernPairs1", 2, ParseStartKernPairs, FM(nKernPairs) },
+ { "StartTrackKern", 2, ParseStartTrackKern, FM(nTrackKern) },
+};
+static int nKernDataSpecs = sizeof(kernDataSpecs) / sizeof(ParserSpec);
+
+static int
+ParseStartKernData(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ int result;
+
+ do {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartKernPairs");
+ }
+ result = ParseLine(parserPtr, kernDataSpecs, nKernDataSpecs, afmPtr);
+ } while (result == TCL_OK);
+ if (result == TCL_CONTINUE) {
+ return TCL_OK; /* Found EndKernData */
+ }
+ return TCL_ERROR;
+}
+
+
+static int
+ParseLigature(Parser *parserPtr, char *record, int offset)
+{
+ return TCL_OK;
+}
+
+static ParserSpec charMetricsSpecs[] = {
+ { "B", 5, ParseBBox, CM(bbox) },
+ { "C", 2, ParseInt, CM(index) },
+ { "CH", 2, ParseHex, CM(index) },
+ { "EndCharMetrics", 1, ParseEndSection, 0 },
+ { "L", 3, ParseLigature, CM(hasLigature) },
+ { "N", 2, ParseName, CM(name) },
+ { "VV", 3, ParsePoint, CM(vVector) },
+ { "W", 3, ParsePoint, CM(w) },
+ { "W0", 3, ParsePoint, CM(w) },
+ { "W1", 3, ParsePoint, CM(w) },
+ { "W0X", 2, ParseNumber, CM(w.x) },
+ { "W0Y", 2, ParseNumber, CM(w.y) },
+ { "W1X", 2, ParseNumber, CM(w.x) },
+ { "W1Y", 2, ParseNumber, CM(w.y) },
+ { "WX", 2, ParseNumber, CM(w.x) },
+ { "WY", 2, ParseNumber, CM(w.y) }
+};
+static int nCharMetricsSpecs = sizeof(charMetricsSpecs) / sizeof(ParserSpec);
+
+static int
+ParseStartCharMetrics(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ int *valuePtr = (int *)(record + offset);
+ int count;
+ int i;
+
+ assert(*valuePtr == 0);
+ if (Tcl_GetInt(NULL, parserPtr->argv[1], &i) != TCL_OK) {
+ ParserError(parserPtr, "can't convert \"%s\" to integer.",
+ parserPtr->argv[1]);
+ }
+ i++;
+ *valuePtr = i;
+ for(i = 0; i < 256; i++) {
+ afmPtr->metrics[i].index = -1;
+ }
+ count = 0;
+ for (;;) {
+ int result;
+ CharMetrics cm;
+ const char *p;
+
+ result = GetLine(parserPtr);
+ if (result == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartCharMetrics");
+ }
+ memset(&cm, 0, sizeof(CharMetrics));
+ for(p = strtok(Tcl_DStringValue(&parserPtr->lastLine), ";"); p != NULL;
+ p = strtok(NULL, ";")) {
+ SplitLine(parserPtr, p);
+ if (parserPtr->argc == 0) {
+ continue;
+ }
+ result = ParseLine(parserPtr, charMetricsSpecs, nCharMetricsSpecs,
+ &cm);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ count++;
+ if (cm.index != -1) {
+ if (cm.name != NULL) {
+ UpdateSymbol(parserPtr->afmPtr, cm.index, cm.name);
+ }
+ afmPtr->metrics[cm.index] = cm;
+ }
+ if (result == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+ if (result == TCL_CONTINUE) {
+ assert(count == *valuePtr);
+ return TCL_OK; /* Found EndCharMetrics */
+ }
+ }
+ return TCL_ERROR;
+}
+
+static ParserSpec fontMetricsSpecs[] = {
+ { "Ascender", 2, ParseNumber, FM(ascender) },
+ { "CapHeight", 2, ParseNumber, FM(capHeight) },
+ { "CharWidth", 3, ParsePoint, FM(charWidth) },
+ { "CharacterSet", 0, ParseString, FM(characterSet) },
+ { "Characters", 2, ParseInt, FM(characters) },
+ { "Comment", 0, NULL, FM(comment) },
+ { "Copyright", 0, NULL, FM(copyright) },
+ { "Descender", 2, ParseNumber, FM(descender) },
+ { "EncodingScheme", 0, ParseString, FM(encodingScheme) },
+ { "EndFontMetrics", 1, ParseEndSection, 0 },
+ { "EscChar", 2, ParseInt, FM(escChar) },
+ { "FamilyName", 0, ParseString, FM(familyName) },
+ { "FontBBox", 5, ParseBBox, FM(fontBBox) },
+ { "FontName", 0, ParseString, FM(fontName) },
+ { "FullName", 0, ParseString, FM(fullName) },
+ { "IsBaseFont", 2, ParseBoolean, FM(isBaseFont) },
+ { "IsCIDFont", 2, ParseBoolean, FM(isCIDFont) },
+ { "IsFixedPitch", 2, ParseBoolean, FM(isFixedPitch) },
+ { "IsFixedV", 2, ParseBoolean, FM(isFixedV) },
+ { "ItalicAngle", 2, ParseNumber, FM(italicAngle) },
+ { "MappingScheme", 2, ParseInt, FM(mappingScheme) },
+ { "MetricSets", 2, ParseInt, FM(metricSets) },
+ { "Notice", 0, NULL, FM(notice) },
+ { "StartCharMetrics", 2, ParseStartCharMetrics, FM(nCharMetrics) },
+ { "StartComposites", 2, ParseStartComposites, FM(nComposites) },
+ { "StartDirection", 2, ParseStartDirection, FM(nDirection) },
+ { "StartKernData", 1, ParseStartKernData, 0 },
+ { "StdHW", 2, ParseNumber, FM(stdHW) },
+ { "StdVW", 2, ParseNumber, FM(stdVW) },
+ { "UnderlinePosition", 2, ParseNumber, FM(underlinePosition) },
+ { "UnderlineThickness", 2, ParseNumber, FM(underlineThickness) },
+ { "VVector", 2, ParsePoint, FM(vVector) },
+ { "Version", 0, ParseString, FM(version) },
+ { "Weight", 0, ParseString, FM(weight) },
+ { "XHeight", 2, ParseNumber, FM(xHeight) }
+};
+static int nFontMetricsSpecs = sizeof(fontMetricsSpecs) / sizeof(ParserSpec);
+
+static int
+ParseStartFontMetrics(Parser *parserPtr, char *record, int offset)
+{
+ AdobeFontMetrics *afmPtr = (AdobeFontMetrics *)record;
+ const char **versionPtr = (const char **)(record + offset);
+ int result;
+
+ assert(*versionPtr == NULL);
+ *versionPtr = Blt_Strdup(parserPtr->argv[1]);
+ do {
+ if (SplitNextLine(parserPtr) == TCL_RETURN) {
+ ParserError(parserPtr, "unexpected EOF in StartFontMetrics");
+ }
+ result = ParseLine(parserPtr, fontMetricsSpecs, nFontMetricsSpecs,
+ afmPtr);
+ } while (result == TCL_OK);
+ if (result == TCL_CONTINUE) {
+ return TCL_OK; /* Found EndFontMetrics */
+ }
+ return TCL_ERROR;
+}
+
+static ParserSpec afmSpecs[] = {
+ { "StartFontMetrics", 2, ParseStartFontMetrics, FM(afmVersion) },
+};
+static int nAfmSpecs = sizeof(afmSpecs) / sizeof(ParserSpec);
+
+static AdobeFontMetrics *
+ParseAdobeFontMetricsFile(Tcl_Interp *interp, const char *fileName)
+{
+ AdobeFontMetrics *afmPtr;
+ Parser *parserPtr;
+ int result;
+
+ afmPtr = calloc(1, sizeof(AdobeFontMetrics));
+ assert(afmPtr);
+ parserPtr = NewParser(afmPtr, fileName);
+ if (parserPtr == NULL) {
+ free(afmPtr);
+ return NULL;
+ }
+ /* Set up jump for errors. */
+ if (setjmp(parserPtr->jmpbuf)) {
+ fprintf(stderr, "%s\n", Tcl_DStringValue(&parserPtr->errors));
+ DestroyParser(parserPtr);
+ DestroyAdobeFontMetrics(afmPtr);
+ return NULL;
+ }
+ for (;;) {
+ result = SplitNextLine(parserPtr);
+ if (result == TCL_RETURN) {
+ break;
+ }
+ result = ParseLine(parserPtr, afmSpecs, nAfmSpecs, afmPtr);
+ }
+ DestroyParser(parserPtr);
+ if (result != TCL_RETURN) {
+ DestroyAdobeFontMetrics(afmPtr);
+ return NULL;
+ }
+ BuildKernPairsTable(afmPtr);
+ return afmPtr;
+}
+
+typedef struct {
+ const char *alias;
+ const char *fontName;
+} FontMap;
+
+static FontMap psFontMap[] =
+{
+ { "Arial", "Helvetica" },
+ { "AvantGarde", "AvantGarde" },
+ { "Bookman", "Bookman" },
+ { "Courier New", "Courier" },
+ { "Courier", "Courier" },
+ { "Geneva", "Helvetica" },
+ { "Helvetica", "Helvetica" },
+ { "Mathematica1", "Helvetica" },
+ { "Monaco", "Courier" },
+ { "New Century Schoolbook", "NewCenturySchlbk" },
+ { "New York", "Times" },
+ { "Nimbus Roman No9 L" "Times" },
+ { "Nimbus Sans L Condensed","Helvetica" },
+ { "Nimbus Sans L", "Helvetica" },
+ { "Palatino", "Palatino" },
+ { "Standard Symbols L", "Symbol" },
+ { "Symbol", "Symbol" },
+ { "Times New Roman", "Times" },
+ { "Times Roman", "Times" },
+ { "Times", "Times" },
+ { "ZapfChancery", "ZapfChancery" },
+ { "ZapfDingbats", "ZapfDingbats" }
+};
+static int nPsFonts = sizeof(psFontMap) / sizeof(FontMap);
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LookupFontName --
+ *
+ *---------------------------------------------------------------------------
+ */
+static const char *
+LookupFontName(const char *string)
+{
+ char c;
+ int high, low;
+
+ low = 0;
+ high = nPsFonts - 1;
+ c = string[0];
+ while (low <= high) {
+ FontMap *mapPtr;
+ int compare;
+ int median;
+
+ median = (low + high) >> 1;
+ mapPtr = psFontMap + median;
+
+ /* Test the first character */
+ compare = c - mapPtr->alias[0];
+ if (compare == 0) {
+ /* Now test the entire string */
+ compare = strcmp(string, mapPtr->alias);
+ }
+ if (compare < 0) {
+ high = median - 1;
+ } else if (compare > 0) {
+ low = median + 1;
+ } else {
+ return mapPtr->fontName;
+ }
+ }
+ return "Helvetica"; /* Can't find font. */
+}
+
+static AdobeFontMetrics *
+GetAdobeFontMetrics(Tcl_Interp *interp, const char *psFontName)
+{
+ AdobeFontMetrics *afmPtr;
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ if (!initialized) {
+ Blt_InitHashTable(&fontTable, BLT_STRING_KEYS);
+ initialized = TRUE;
+ }
+ psFontName = LookupFontName(psFontName);
+ hPtr = Blt_CreateHashEntry(&fontTable, psFontName, &isNew);
+ if (isNew) {
+ const char *path;
+ Tcl_DString ds;
+
+ path = Tcl_GetVar(interp, "tlt_library", TCL_GLOBAL_ONLY);
+ if (path == NULL) {
+ Tcl_AppendResult(interp, "can't find \"tlt_library\" variable",
+ (char *)NULL);
+ Blt_DeleteHashEntry(&fontTable, hPtr);
+ return NULL;
+ }
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, path, -1);
+ Tcl_DStringAppend(&ds, "/afm/", 5);
+ Tcl_DStringAppend(&ds, psFontName, -1);
+ Tcl_DStringAppend(&ds, ".afm", 4);
+ afmPtr = ParseAdobeFontMetricsFile(interp, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ if (afmPtr == NULL) {
+ Blt_DeleteHashEntry(&fontTable, hPtr);
+ return NULL;
+ }
+ Blt_SetHashValue(hPtr, afmPtr);
+ afmPtr->hashPtr = hPtr;
+ } else {
+ afmPtr = Blt_GetHashValue(hPtr);
+ }
+ return afmPtr;
+}
+
+static AdobeFontMetrics *
+GetAdobeFontMetricsFromFont(Blt_Font font)
+{
+ AdobeFontMetrics *afmPtr;
+ Tcl_DString ds;
+ double pointSize;
+ Tcl_Interp *interp;
+
+ Tcl_DStringInit(&ds);
+ pointSize = Blt_PostscriptFontName(font, &ds);
+ interp = Blt_GetFontInterp(font);
+ afmPtr = GetAdobeFontMetrics(interp, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ if (afmPtr != NULL) {
+ afmPtr->pointSize = pointSize;
+ return afmPtr;
+ }
+ return NULL;
+}
+
+int
+Blt_Ps_GetFontMetrics(Blt_Font font, Blt_FontMetrics *fmPtr)
+{
+ AdobeFontMetrics *afmPtr;
+
+ afmPtr = GetAdobeFontMetricsFromFont(font);
+ if (afmPtr == NULL) {
+ return TCL_ERROR;
+ }
+ fmPtr->ascent = Points(afmPtr, afmPtr->ascender);
+ fmPtr->descent = Points(afmPtr, -afmPtr->descender);
+ fmPtr->linespace = Points(afmPtr, afmPtr->ascender - afmPtr->descender);
+ return TCL_OK;
+}
+
+int
+Blt_Ps_TextWidth(Blt_Font font, const char *string, int nBytes)
+{
+ AdobeFontMetrics *afmPtr;
+ const char *p, *pend;
+ float width;
+
+ afmPtr = GetAdobeFontMetricsFromFont(font);
+ if (afmPtr == NULL) {
+ fprintf(stderr, "can't find font\n");
+ return -1;
+ }
+ width = 0;
+ for (p = string, pend = string + nBytes; p < pend; /*empty*/) {
+ CharMetrics *cmPtr;
+ unsigned char c;
+ Tcl_UniChar ch;
+
+ p += Tcl_UtfToUniChar(p, &ch);
+ c = (unsigned char)(ch & 0xff);
+ cmPtr = afmPtr->metrics + c;
+ if (cmPtr->index < 0) {
+ continue; /* Ignore unencoded characters. */
+ }
+ width += cmPtr->w.x;
+ }
+ {
+ /* Kerning */
+ unsigned char c1, c2;
+ Tcl_UniChar ch;
+
+ p = string;
+ p += Tcl_UtfToUniChar(string, &ch);
+ c1 = (unsigned char)(ch & 0xff);
+ while (p < pend) {
+ p += Tcl_UtfToUniChar(p, &ch);
+ c2 = (unsigned char)(ch & 0xff);
+ if (afmPtr->metrics[c1].hasKernPair) {
+ KernPairs *kp;
+
+ kp = GetKernPairs(afmPtr, c1, c2);
+ width += kp->x;
+ }
+ c1 = c2;
+ }
+ }
+ return Points(afmPtr, width);
+}
+
diff --git a/tlt3.0/bltPsInt.h b/tlt3.0/bltPsInt.h
new file mode 100644
index 0000000..4b552c4
--- /dev/null
+++ b/tlt3.0/bltPsInt.h
@@ -0,0 +1,49 @@
+
+/*
+ * bltPsInt.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_PS_INT_H
+#define _BLT_PS_INT_H
+
+#include "bltPs.h"
+
+struct _Blt_Ps {
+ Tcl_Interp *interp; /* Interpreter to report errors to. */
+
+ Tcl_DString dString; /* Dynamic string used to contain the
+ * PostScript generated. */
+ PageSetup *setupPtr;
+
+#define POSTSCRIPT_BUFSIZ ((BUFSIZ*2)-1)
+ /*
+ * Utility space for building strings. Currently used to create
+ * PostScript output for the "postscript" command.
+ */
+ char scratchArr[POSTSCRIPT_BUFSIZ+1];
+};
+
+typedef struct _Blt_Ps PostScript;
+
+#endif /* BLT_PS_H */
diff --git a/tlt3.0/bltSpline.c b/tlt3.0/bltSpline.c
new file mode 100644
index 0000000..fb1a297
--- /dev/null
+++ b/tlt3.0/bltSpline.c
@@ -0,0 +1,1287 @@
+/*
+ * Copyright 2009 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+
+#include "bltInt.h"
+#include "bltSpline.h"
+#include "bltOp.h"
+#include "bltVector.h"
+
+typedef int (SplineProc)(Point2d origPts[], int nOrigPts, Point2d intpPts[],
+ int nIntpPts);
+
+typedef double TriDiagonalMatrix[3];
+typedef struct {
+ double b, c, d;
+} Cubic2D;
+
+typedef struct {
+ double b, c, d, e, f;
+} Quint2D;
+
+/*
+ * Quadratic spline parameters
+ */
+#define E1 param[0]
+#define E2 param[1]
+#define V1 param[2]
+#define V2 param[3]
+#define W1 param[4]
+#define W2 param[5]
+#define Z1 param[6]
+#define Z2 param[7]
+#define Y1 param[8]
+#define Y2 param[9]
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Search --
+ *
+ * Conducts a binary search for a value. This routine is called
+ * only if key is between x(0) and x(len - 1).
+ *
+ * Results:
+ * Returns the index of the largest value in xtab for which
+ * x[i] < key.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+Search(
+ Point2d points[], /* Contains the abscissas of the data
+ * points of interpolation. */
+ int nPoints, /* Dimension of x. */
+ double key, /* Value whose relative position in
+ * x is to be located. */
+ int *foundPtr) /* (out) Returns 1 if s is found in
+ * x and 0 otherwise. */
+{
+ int high, low, mid;
+
+ low = 0;
+ high = nPoints - 1;
+
+ while (high >= low) {
+ mid = (high + low) / 2;
+ if (key > points[mid].x) {
+ low = mid + 1;
+ } else if (key < points[mid].x) {
+ high = mid - 1;
+ } else {
+ *foundPtr = 1;
+ return mid;
+ }
+ }
+ *foundPtr = 0;
+ return low;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadChoose --
+ *
+ * Determines the case needed for the computation of the parame-
+ * ters of the quadratic spline.
+ *
+ * Results:
+ * Returns a case number (1-4) which controls how the parameters
+ * of the quadratic spline are evaluated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+QuadChoose(
+ Point2d *p, /* Coordinates of one of the points of
+ * interpolation */
+ Point2d *q, /* Coordinates of one of the points of
+ * interpolation */
+ double m1, /* Derivative condition at point P */
+ double m2, /* Derivative condition at point Q */
+ double epsilon) /* Error tolerance used to distinguish
+ * cases when m1 or m2 is relatively
+ * close to the slope or twice the
+ * slope of the line segment joining
+ * the points P and Q. If
+ * epsilon is not 0.0, then epsilon
+ * should be greater than or equal to
+ * machine epsilon. */
+{
+ double slope;
+
+ /* Calculate the slope of the line joining P and Q. */
+ slope = (q->y - p->y) / (q->x - p->x);
+
+ if (slope != 0.0) {
+ double relerr;
+ double mref, mref1, mref2, prod1, prod2;
+
+ prod1 = slope * m1;
+ prod2 = slope * m2;
+
+ /* Find the absolute values of the slopes slope, m1, and m2. */
+ mref = fabs(slope);
+ mref1 = fabs(m1);
+ mref2 = fabs(m2);
+
+ /*
+ * If the relative deviation of m1 or m2 from slope is less than
+ * epsilon, then choose case 2 or case 3.
+ */
+ relerr = epsilon * mref;
+ if ((fabs(slope - m1) > relerr) && (fabs(slope - m2) > relerr) &&
+ (prod1 >= 0.0) && (prod2 >= 0.0)) {
+ double prod;
+
+ prod = (mref - mref1) * (mref - mref2);
+ if (prod < 0.0) {
+ /*
+ * l1, the line through (x1,y1) with slope m1, and l2,
+ * the line through (x2,y2) with slope m2, intersect
+ * at a point whose abscissa is between x1 and x2.
+ * The abscissa becomes a knot of the spline.
+ */
+ return 1;
+ }
+ if (mref1 > (mref * 2.0)) {
+ if (mref2 <= ((2.0 - epsilon) * mref)) {
+ return 3;
+ }
+ } else if (mref2 <= (mref * 2.0)) {
+ /*
+ * Both l1 and l2 cross the line through
+ * (x1+x2)/2.0,y1 and (x1+x2)/2.0,y2, which is the
+ * midline of the rectangle formed by P and Q or both
+ * m1 and m2 have signs different than the sign of
+ * slope, or one of m1 and m2 has opposite sign from
+ * slope and l1 and l2 intersect to the left of x1 or
+ * to the right of x2. The point (x1+x2)/2. is a knot
+ * of the spline.
+ */
+ return 2;
+ } else if (mref1 <= ((2.0 - epsilon) * mref)) {
+ /*
+ * In cases 3 and 4, sign(m1)=sign(m2)=sign(slope).
+ * Either l1 or l2 crosses the midline, but not both.
+ * Choose case 4 if mref1 is greater than
+ * (2.-epsilon)*mref; otherwise, choose case 3.
+ */
+ return 3;
+ }
+ /*
+ * If neither l1 nor l2 crosses the midline, the spline
+ * requires two knots between x1 and x2.
+ */
+ return 4;
+ } else {
+ /*
+ * The sign of at least one of the slopes m1 or m2 does not
+ * agree with the sign of *slope*.
+ */
+ if ((prod1 < 0.0) && (prod2 < 0.0)) {
+ return 2;
+ } else if (prod1 < 0.0) {
+ if (mref2 > ((epsilon + 1.0) * mref)) {
+ return 1;
+ } else {
+ return 2;
+ }
+ } else if (mref1 > ((epsilon + 1.0) * mref)) {
+ return 1;
+ } else {
+ return 2;
+ }
+ }
+ } else if ((m1 * m2) >= 0.0) {
+ return 2;
+ } else {
+ return 1;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadCases --
+ *
+ * Computes the knots and other parameters of the spline on the
+ * interval PQ.
+ *
+ *
+ * On input--
+ *
+ * P and Q are the coordinates of the points of interpolation.
+ *
+ * m1 is the slope at P.
+ *
+ * m2 is the slope at Q.
+ *
+ * ncase controls the number and location of the knots.
+ *
+ *
+ * On output--
+ *
+ * (v1,v2),(w1,w2),(z1,z2), and (e1,e2) are the coordinates of
+ * the knots and other parameters of the spline on P.
+ * (e1,e2) and Q are used only if ncase=4.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+QuadCases(Point2d *p, Point2d *q, double m1, double m2, double param[],
+ int which)
+{
+ if ((which == 3) || (which == 4)) { /* Parameters used in both 3 and 4 */
+ double mbar1, mbar2, mbar3, c1, d1, h1, j1, k1;
+
+ c1 = p->x + (q->y - p->y) / m1;
+ d1 = q->x + (p->y - q->y) / m2;
+ h1 = c1 * 2.0 - p->x;
+ j1 = d1 * 2.0 - q->x;
+ mbar1 = (q->y - p->y) / (h1 - p->x);
+ mbar2 = (p->y - q->y) / (j1 - q->x);
+
+ if (which == 4) { /* Case 4. */
+ Y1 = (p->x + c1) / 2.0;
+ V1 = (p->x + Y1) / 2.0;
+ V2 = m1 * (V1 - p->x) + p->y;
+ Z1 = (d1 + q->x) / 2.0;
+ W1 = (q->x + Z1) / 2.0;
+ W2 = m2 * (W1 - q->x) + q->y;
+ mbar3 = (W2 - V2) / (W1 - V1);
+ Y2 = mbar3 * (Y1 - V1) + V2;
+ Z2 = mbar3 * (Z1 - V1) + V2;
+ E1 = (Y1 + Z1) / 2.0;
+ E2 = mbar3 * (E1 - V1) + V2;
+ } else { /* Case 3. */
+ k1 = (p->y - q->y + q->x * mbar2 - p->x * mbar1) / (mbar2 - mbar1);
+ if (fabs(m1) > fabs(m2)) {
+ Z1 = (k1 + p->x) / 2.0;
+ } else {
+ Z1 = (k1 + q->x) / 2.0;
+ }
+ V1 = (p->x + Z1) / 2.0;
+ V2 = p->y + m1 * (V1 - p->x);
+ W1 = (q->x + Z1) / 2.0;
+ W2 = q->y + m2 * (W1 - q->x);
+ Z2 = V2 + (W2 - V2) / (W1 - V1) * (Z1 - V1);
+ }
+ } else if (which == 2) { /* Case 2. */
+ Z1 = (p->x + q->x) / 2.0;
+ V1 = (p->x + Z1) / 2.0;
+ V2 = p->y + m1 * (V1 - p->x);
+ W1 = (Z1 + q->x) / 2.0;
+ W2 = q->y + m2 * (W1 - q->x);
+ Z2 = (V2 + W2) / 2.0;
+ } else { /* Case 1. */
+ double ztwo;
+
+ Z1 = (p->y - q->y + m2 * q->x - m1 * p->x) / (m2 - m1);
+ ztwo = p->y + m1 * (Z1 - p->x);
+ V1 = (p->x + Z1) / 2.0;
+ V2 = (p->y + ztwo) / 2.0;
+ W1 = (Z1 + q->x) / 2.0;
+ W2 = (ztwo + q->y) / 2.0;
+ Z2 = V2 + (W2 - V2) / (W1 - V1) * (Z1 - V1);
+ }
+}
+
+static int
+QuadSelect(Point2d *p, Point2d *q, double m1, double m2, double epsilon,
+ double param[])
+{
+ int ncase;
+
+ ncase = QuadChoose(p, q, m1, m2, epsilon);
+ QuadCases(p, q, m1, m2, param, ncase);
+ return ncase;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadGetImage --
+ *
+ *---------------------------------------------------------------------------
+ */
+INLINE static double
+QuadGetImage(double p1, double p2, double p3, double x1, double x2, double x3)
+{
+ double A, B, C;
+ double y;
+
+ A = x1 - x2;
+ B = x2 - x3;
+ C = x1 - x3;
+
+ y = (p1 * (A * A) + p2 * 2.0 * B * A + p3 * (B * B)) / (C * C);
+ return y;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadSpline --
+ *
+ * Finds the image of a point in x.
+ *
+ * On input
+ *
+ * x Contains the value at which the spline is evaluated.
+ * leftX, leftY
+ * Coordinates of the left-hand data point used in the
+ * evaluation of x values.
+ * rightX, rightY
+ * Coordinates of the right-hand data point used in the
+ * evaluation of x values.
+ * Z1, Z2, Y1, Y2, E2, W2, V2
+ * Parameters of the spline.
+ * ncase Controls the evaluation of the spline by indicating
+ * whether one or two knots were placed in the interval
+ * (xtabs,xtabs1).
+ *
+ * Results:
+ * The image of the spline at x.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+QuadSpline(
+ Point2d *intp, /* Value at which spline is evaluated */
+ Point2d *left, /* Point to the left of the data point to
+ * be evaluated */
+ Point2d *right, /* Point to the right of the data point to
+ * be evaluated */
+ double param[], /* Parameters of the spline */
+ int ncase) /* Controls the evaluation of the
+ * spline by indicating whether one or
+ * two knots were placed in the
+ * interval (leftX,rightX) */
+{
+ double y;
+
+ if (ncase == 4) {
+ /*
+ * Case 4: More than one knot was placed in the interval.
+ */
+
+ /*
+ * Determine the location of data point relative to the 1st knot.
+ */
+ if (Y1 > intp->x) {
+ y = QuadGetImage(left->y, V2, Y2, Y1, intp->x, left->x);
+ } else if (Y1 < intp->x) {
+ /*
+ * Determine the location of the data point relative to
+ * the 2nd knot.
+ */
+ if (Z1 > intp->x) {
+ y = QuadGetImage(Y2, E2, Z2, Z1, intp->x, Y1);
+ } else if (Z1 < intp->x) {
+ y = QuadGetImage(Z2, W2, right->y, right->x, intp->x, Z1);
+ } else {
+ y = Z2;
+ }
+ } else {
+ y = Y2;
+ }
+ } else {
+
+ /*
+ * Cases 1, 2, or 3:
+ *
+ * Determine the location of the data point relative to the
+ * knot.
+ */
+ if (Z1 < intp->x) {
+ y = QuadGetImage(Z2, W2, right->y, right->x, intp->x, Z1);
+ } else if (Z1 > intp->x) {
+ y = QuadGetImage(left->y, V2, Z2, Z1, intp->x, left->x);
+ } else {
+ y = Z2;
+ }
+ }
+ intp->y = y;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadSlopes --
+ *
+ * Calculates the derivative at each of the data points. The
+ * slopes computed will insure that an osculatory quadratic
+ * spline will have one additional knot between two adjacent
+ * points of interpolation. Convexity and monotonicity are
+ * preserved wherever these conditions are compatible with the
+ * data.
+ *
+ * Results:
+ * The output array "m" is filled with the derivates at each
+ * data point.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+QuadSlopes(Point2d *points, double *m, int nPoints)
+{
+ double xbar, xmid, xhat, ydif1, ydif2;
+ double yxmid;
+ double m1, m2;
+ double m1s, m2s;
+ int i, n, l;
+
+ m1s = m2s = m1 = m2 = 0;
+ for (l = 0, i = 1, n = 2; i < (nPoints - 1); l++, i++, n++) {
+ /*
+ * Calculate the slopes of the two lines joining three
+ * consecutive data points.
+ */
+ ydif1 = points[i].y - points[l].y;
+ ydif2 = points[n].y - points[i].y;
+ m1 = ydif1 / (points[i].x - points[l].x);
+ m2 = ydif2 / (points[n].x - points[i].x);
+ if (i == 1) {
+ m1s = m1, m2s = m2; /* Save slopes of starting point */
+ }
+ /*
+ * If one of the preceding slopes is zero or if they have opposite
+ * sign, assign the value zero to the derivative at the middle
+ * point.
+ */
+ if ((m1 == 0.0) || (m2 == 0.0) || ((m1 * m2) <= 0.0)) {
+ m[i] = 0.0;
+ } else if (fabs(m1) > fabs(m2)) {
+ /*
+ * Calculate the slope by extending the line with slope m1.
+ */
+ xbar = ydif2 / m1 + points[i].x;
+ xhat = (xbar + points[n].x) / 2.0;
+ m[i] = ydif2 / (xhat - points[i].x);
+ } else {
+ /*
+ * Calculate the slope by extending the line with slope m2.
+ */
+ xbar = -ydif1 / m2 + points[i].x;
+ xhat = (points[l].x + xbar) / 2.0;
+ m[i] = ydif1 / (points[i].x - xhat);
+ }
+ }
+
+ /* Calculate the slope at the last point, x(n). */
+ i = nPoints - 2;
+ n = nPoints - 1;
+ if ((m1 * m2) < 0.0) {
+ m[n] = m2 * 2.0;
+ } else {
+ xmid = (points[i].x + points[n].x) / 2.0;
+ yxmid = m[i] * (xmid - points[i].x) + points[i].y;
+ m[n] = (points[n].y - yxmid) / (points[n].x - xmid);
+ if ((m[n] * m2) < 0.0) {
+ m[n] = 0.0;
+ }
+ }
+
+ /* Calculate the slope at the first point, x(0). */
+ if ((m1s * m2s) < 0.0) {
+ m[0] = m1s * 2.0;
+ } else {
+ xmid = (points[0].x + points[1].x) / 2.0;
+ yxmid = m[1] * (xmid - points[1].x) + points[1].y;
+ m[0] = (yxmid - points[0].y) / (xmid - points[0].x);
+ if ((m[0] * m1s) < 0.0) {
+ m[0] = 0.0;
+ }
+ }
+
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * QuadEval --
+ *
+ * QuadEval controls the evaluation of an osculatory quadratic
+ * spline. The user may provide his own slopes at the points of
+ * interpolation or use the subroutine 'QuadSlopes' to calculate
+ * slopes which are consistent with the shape of the data.
+ *
+ * ON INPUT--
+ * intpPts must be a nondecreasing vector of points at which the
+ * spline will be evaluated.
+ * origPts contains the abscissas of the data points to be
+ * interpolated. xtab must be increasing.
+ * y contains the ordinates of the data points to be
+ * interpolated.
+ * m contains the slope of the spline at each point of
+ * interpolation.
+ * nPoints number of data points (dimension of xtab and y).
+ * numEval is the number of points of evaluation (dimension of
+ * xval and yval).
+ * epsilon is a relative error tolerance used in subroutine
+ * 'QuadChoose' to distinguish the situation m(i) or
+ * m(i+1) is relatively close to the slope or twice
+ * the slope of the linear segment between xtab(i) and
+ * xtab(i+1). If this situation occurs, roundoff may
+ * cause a change in convexity or monotonicity of the
+ * resulting spline and a change in the case number
+ * provided by 'QuadChoose'. If epsilon is not equal to zero,
+ * then epsilon should be greater than or equal to machine
+ * epsilon.
+ * ON OUTPUT--
+ * yval contains the images of the points in xval.
+ * err is one of the following error codes:
+ * 0 - QuadEval ran normally.
+ * 1 - xval(i) is less than xtab(1) for at least one
+ * i or xval(i) is greater than xtab(num) for at
+ * least one i. QuadEval will extrapolate to provide
+ * function values for these abscissas.
+ * 2 - xval(i+1) < xval(i) for some i.
+ *
+ *
+ * QuadEval calls the following subroutines or functions:
+ * Search
+ * QuadCases
+ * QuadChoose
+ * QuadSpline
+ *---------------------------------------------------------------------------
+ */
+static int
+QuadEval(
+ Point2d origPts[],
+ int nOrigPts,
+ Point2d intpPts[],
+ int nIntpPts,
+ double *m, /* Slope of the spline at each point
+ * of interpolation. */
+ double epsilon) /* Relative error tolerance (see choose) */
+{
+ int error;
+ int i, j;
+ double param[10];
+ int ncase;
+ int start, end;
+ int l, p;
+ int n;
+ int found;
+
+ /* Initialize indices and set error result */
+ error = 0;
+ l = nOrigPts - 1;
+ p = l - 1;
+ ncase = 1;
+
+ /*
+ * Determine if abscissas of new vector are non-decreasing.
+ */
+ for (j = 1; j < nIntpPts; j++) {
+ if (intpPts[j].x < intpPts[j - 1].x) {
+ return 2;
+ }
+ }
+ /*
+ * Determine if any of the points in xval are LESS than the
+ * abscissa of the first data point.
+ */
+ for (start = 0; start < nIntpPts; start++) {
+ if (intpPts[start].x >= origPts[0].x) {
+ break;
+ }
+ }
+ /*
+ * Determine if any of the points in xval are GREATER than the
+ * abscissa of the l data point.
+ */
+ for (end = nIntpPts - 1; end >= 0; end--) {
+ if (intpPts[end].x <= origPts[l].x) {
+ break;
+ }
+ }
+
+ if (start > 0) {
+ error = 1; /* Set error value to indicate that
+ * extrapolation has occurred. */
+ /*
+ * Calculate the images of points of evaluation whose abscissas
+ * are less than the abscissa of the first data point.
+ */
+ ncase = QuadSelect(origPts, origPts + 1, m[0], m[1], epsilon, param);
+ for (j = 0; j < (start - 1); j++) {
+ QuadSpline(intpPts + j, origPts, origPts + 1, param, ncase);
+ }
+ if (nIntpPts == 1) {
+ return error;
+ }
+ }
+ if ((nIntpPts == 1) && (end != (nIntpPts - 1))) {
+ goto noExtrapolation;
+ }
+
+ /*
+ * Search locates the interval in which the first in-range
+ * point of evaluation lies.
+ */
+
+ i = Search(origPts, nOrigPts, intpPts[start].x, &found);
+
+ n = i + 1;
+ if (n >= nOrigPts) {
+ n = nOrigPts - 1;
+ i = nOrigPts - 2;
+ }
+ /*
+ * If the first in-range point of evaluation is equal to one
+ * of the data points, assign the appropriate value from y.
+ * Continue until a point of evaluation is found which is not
+ * equal to a data point.
+ */
+ if (found) {
+ do {
+ intpPts[start].y = origPts[i].y;
+ start++;
+ if (start >= nIntpPts) {
+ return error;
+ }
+ } while (intpPts[start - 1].x == intpPts[start].x);
+
+ for (;;) {
+ if (intpPts[start].x < origPts[n].x) {
+ break; /* Break out of for-loop */
+ }
+ if (intpPts[start].x == origPts[n].x) {
+ do {
+ intpPts[start].y = origPts[n].y;
+ start++;
+ if (start >= nIntpPts) {
+ return error;
+ }
+ } while (intpPts[start].x == intpPts[start - 1].x);
+ }
+ i++;
+ n++;
+ }
+ }
+ /*
+ * Calculate the images of all the points which lie within
+ * range of the data.
+ */
+ if ((i > 0) || (error != 1)) {
+ ncase = QuadSelect(origPts + i, origPts + n, m[i], m[n],
+ epsilon, param);
+ }
+ for (j = start; j <= end; j++) {
+ /*
+ * If xx(j) - x(n) is negative, do not recalculate
+ * the parameters for this section of the spline since
+ * they are already known.
+ */
+ if (intpPts[j].x == origPts[n].x) {
+ intpPts[j].y = origPts[n].y;
+ continue;
+ } else if (intpPts[j].x > origPts[n].x) {
+ double delta;
+
+ /* Determine that the routine is in the correct part of
+ the spline. */
+ do {
+ i++, n++;
+ delta = intpPts[j].x - origPts[n].x;
+ } while (delta > 0.0);
+
+ if (delta < 0.0) {
+ ncase = QuadSelect(origPts + i, origPts + n, m[i],
+ m[n], epsilon, param);
+ } else if (delta == 0.0) {
+ intpPts[j].y = origPts[n].y;
+ continue;
+ }
+ }
+ QuadSpline(intpPts + j, origPts + i, origPts + n, param, ncase);
+ }
+
+ if (end == (nIntpPts - 1)) {
+ return error;
+ }
+ if ((n == l) && (intpPts[end].x != origPts[l].x)) {
+ goto noExtrapolation;
+ }
+
+ error = 1; /* Set error value to indicate that
+ * extrapolation has occurred. */
+ ncase = QuadSelect(origPts + p, origPts + l, m[p], m[l], epsilon, param);
+
+ noExtrapolation:
+ /*
+ * Calculate the images of the points of evaluation whose
+ * abscissas are greater than the abscissa of the last data point.
+ */
+ for (j = (end + 1); j < nIntpPts; j++) {
+ QuadSpline(intpPts + j, origPts + p, origPts + l, param, ncase);
+ }
+ return error;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Shape preserving quadratic splines
+ * by D.F.Mcallister & J.A.Roulier
+ * Coded by S.L.Dodd & M.Roulier
+ * N.C.State University
+ *
+ *---------------------------------------------------------------------------
+ */
+/*
+ * Driver routine for quadratic spline package
+ * On input--
+ * X,Y Contain n-long arrays of data (x is increasing)
+ * XM Contains m-long array of x values (increasing)
+ * eps Relative error tolerance
+ * n Number of input data points
+ * m Number of output data points
+ * On output--
+ * work Contains the value of the first derivative at each data point
+ * ym Contains the interpolated spline value at each data point
+ */
+int
+Blt_QuadraticSpline(Point2d *origPts, int nOrigPts, Point2d *intpPts,
+ int nIntpPts)
+{
+ double epsilon;
+ double *work;
+ int result;
+
+ work = malloc(nOrigPts * sizeof(double));
+ epsilon = 0.0; /* TBA: adjust error via command-line option */
+ /* allocate space for vectors used in calculation */
+ QuadSlopes(origPts, work, nOrigPts);
+ result = QuadEval(origPts, nOrigPts, intpPts, nIntpPts, work, epsilon);
+ free(work);
+ if (result > 1) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Reference:
+ * Numerical Analysis, R. Burden, J. Faires and A. Reynolds.
+ * Prindle, Weber & Schmidt 1981 pp 112
+ *
+ * Parameters:
+ * origPts - vector of points, assumed to be sorted along x.
+ * intpPts - vector of new points.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_NaturalSpline(Point2d *origPts, int nOrigPts, Point2d *intpPts,
+ int nIntpPts)
+{
+ Cubic2D *eq;
+ Point2d *ip, *iend;
+ TriDiagonalMatrix *A;
+ double *dx; /* vector of deltas in x */
+ double x, dy, alpha;
+ int isKnot;
+ int i, j, n;
+
+ dx = malloc(sizeof(double) * nOrigPts);
+ /* Calculate vector of differences */
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+ dx[i] = origPts[j].x - origPts[i].x;
+ if (dx[i] < 0.0) {
+ return 0;
+ }
+ }
+ n = nOrigPts - 1; /* Number of intervals. */
+ A = malloc(sizeof(TriDiagonalMatrix) * nOrigPts);
+ if (A == NULL) {
+ free(dx);
+ return 0;
+ }
+ /* Vectors to solve the tridiagonal matrix */
+ A[0][0] = A[n][0] = 1.0;
+ A[0][1] = A[n][1] = 0.0;
+ A[0][2] = A[n][2] = 0.0;
+
+ /* Calculate the intermediate results */
+ for (i = 0, j = 1; j < n; j++, i++) {
+ alpha = 3.0 * ((origPts[j + 1].y / dx[j]) - (origPts[j].y / dx[i]) -
+ (origPts[j].y / dx[j]) + (origPts[i].y / dx[i]));
+ A[j][0] = 2 * (dx[j] + dx[i]) - dx[i] * A[i][1];
+ A[j][1] = dx[j] / A[j][0];
+ A[j][2] = (alpha - dx[i] * A[i][2]) / A[j][0];
+ }
+
+ eq = malloc(sizeof(Cubic2D) * nOrigPts);
+ if (eq == NULL) {
+ free(A);
+ free(dx);
+ return FALSE;
+ }
+ eq[0].c = eq[n].c = 0.0;
+ for (j = n, i = n - 1; i >= 0; i--, j--) {
+ eq[i].c = A[i][2] - A[i][1] * eq[j].c;
+ dy = origPts[i+1].y - origPts[i].y;
+ eq[i].b = (dy) / dx[i] - dx[i] * (eq[j].c + 2.0 * eq[i].c) / 3.0;
+ eq[i].d = (eq[j].c - eq[i].c) / (3.0 * dx[i]);
+ }
+ free(A);
+ free(dx);
+
+ /* Now calculate the new values */
+ for (ip = intpPts, iend = ip + nIntpPts; ip < iend; ip++) {
+ ip->y = 0.0;
+ x = ip->x;
+
+ /* Is it outside the interval? */
+ if ((x < origPts[0].x) || (x > origPts[n].x)) {
+ continue;
+ }
+ /* Search for the interval containing x in the point array */
+ i = Search(origPts, nOrigPts, x, &isKnot);
+ if (isKnot) {
+ ip->y = origPts[i].y;
+ } else {
+ i--;
+ x -= origPts[i].x;
+ ip->y = origPts[i].y + x * (eq[i].b + x * (eq[i].c + x * eq[i].d));
+ }
+ }
+ free(eq);
+ return TRUE;
+}
+
+typedef struct {
+ double t; /* Arc length of interval. */
+ double x; /* 2nd derivative of X with respect to T */
+ double y; /* 2nd derivative of Y with respect to T */
+} CubicSpline;
+
+/*
+ * The following two procedures solve the special linear system which arise
+ * in cubic spline interpolation. If x is assumed cyclic ( x[i]=x[n+i] ) the
+ * equations can be written as (i=0,1,...,n-1):
+ * m[i][0] * x[i-1] + m[i][1] * x[i] + m[i][2] * x[i+1] = b[i] .
+ * In matrix notation one gets A * x = b, where the matrix A is tridiagonal
+ * with additional elements in the upper right and lower left position:
+ * A[i][0] = A_{i,i-1} for i=1,2,...,n-1 and m[0][0] = A_{0,n-1} ,
+ * A[i][1] = A_{i, i } for i=0,1,...,n-1
+ * A[i][2] = A_{i,i+1} for i=0,1,...,n-2 and m[n-1][2] = A_{n-1,0}.
+ * A should be symmetric (A[i+1][0] == A[i][2]) and positive definite.
+ * The size of the system is given in n (n>=1).
+ *
+ * In the first procedure the Cholesky decomposition A = C^T * D * C
+ * (C is upper triangle with unit diagonal, D is diagonal) is calculated.
+ * Return TRUE if decomposition exist.
+ */
+static int
+SolveCubic1(TriDiagonalMatrix A[], int n)
+{
+ int i;
+ double m_ij, m_n, m_nn, d;
+
+ if (n < 1) {
+ return FALSE; /* Dimension should be at least 1 */
+ }
+ d = A[0][1]; /* D_{0,0} = A_{0,0} */
+ if (d <= 0.0) {
+ return FALSE; /* A (or D) should be positive definite */
+ }
+ m_n = A[0][0]; /* A_{0,n-1} */
+ m_nn = A[n - 1][1]; /* A_{n-1,n-1} */
+ for (i = 0; i < n - 2; i++) {
+ m_ij = A[i][2]; /* A_{i,1} */
+ A[i][2] = m_ij / d; /* C_{i,i+1} */
+ A[i][0] = m_n / d; /* C_{i,n-1} */
+ m_nn -= A[i][0] * m_n; /* to get C_{n-1,n-1} */
+ m_n = -A[i][2] * m_n; /* to get C_{i+1,n-1} */
+ d = A[i + 1][1] - A[i][2] * m_ij; /* D_{i+1,i+1} */
+ if (d <= 0.0) {
+ return FALSE; /* Elements of D should be positive */
+ }
+ A[i + 1][1] = d;
+ }
+ if (n >= 2) { /* Complete last column */
+ m_n += A[n - 2][2]; /* add A_{n-2,n-1} */
+ A[n - 2][0] = m_n / d; /* C_{n-2,n-1} */
+ A[n - 1][1] = d = m_nn - A[n - 2][0] * m_n; /* D_{n-1,n-1} */
+ if (d <= 0.0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * The second procedure solves the linear system, with the Cholesky
+ * decomposition calculated above (in m[][]) and the right side b given
+ * in x[]. The solution x overwrites the right side in x[].
+ */
+static void
+SolveCubic2(TriDiagonalMatrix A[], CubicSpline spline[], int nIntervals)
+{
+ int i;
+ double x, y;
+ int n, m;
+
+ n = nIntervals - 2;
+ m = nIntervals - 1;
+
+ /* Division by transpose of C : b = C^{-T} * b */
+ x = spline[m].x;
+ y = spline[m].y;
+ for (i = 0; i < n; i++) {
+ spline[i + 1].x -= A[i][2] * spline[i].x; /* C_{i,i+1} * x(i) */
+ spline[i + 1].y -= A[i][2] * spline[i].y; /* C_{i,i+1} * x(i) */
+ x -= A[i][0] * spline[i].x; /* C_{i,n-1} * x(i) */
+ y -= A[i][0] * spline[i].y; /* C_{i,n-1} * x(i) */
+ }
+ if (n >= 0) {
+ /* C_{n-2,n-1} * x_{n-1} */
+ spline[m].x = x - A[n][0] * spline[n].x;
+ spline[m].y = y - A[n][0] * spline[n].y;
+ }
+ /* Division by D: b = D^{-1} * b */
+ for (i = 0; i < nIntervals; i++) {
+ spline[i].x /= A[i][1];
+ spline[i].y /= A[i][1];
+ }
+
+ /* Division by C: b = C^{-1} * b */
+ x = spline[m].x;
+ y = spline[m].y;
+ if (n >= 0) {
+ /* C_{n-2,n-1} * x_{n-1} */
+ spline[n].x -= A[n][0] * x;
+ spline[n].y -= A[n][0] * y;
+ }
+ for (i = (n - 1); i >= 0; i--) {
+ /* C_{i,i+1} * x_{i+1} + C_{i,n-1} * x_{n-1} */
+ spline[i].x -= A[i][2] * spline[i + 1].x + A[i][0] * x;
+ spline[i].y -= A[i][2] * spline[i + 1].y + A[i][0] * y;
+ }
+}
+
+/*
+ * Find second derivatives (x''(t_i),y''(t_i)) of cubic spline interpolation
+ * through list of points (x_i,y_i). The parameter t is calculated as the
+ * length of the linear stroke. The number of points must be at least 3.
+ * Note: For CLOSED_CONTOURs the first and last point must be equal.
+ */
+static CubicSpline *
+CubicSlopes(
+ Point2d points[],
+ int nPoints, /* Number of points (nPoints>=3) */
+ int isClosed, /* CLOSED_CONTOUR or OPEN_CONTOUR */
+ double unitX,
+ double unitY) /* Unit length in x and y (norm=1) */
+{
+ CubicSpline *spline;
+ CubicSpline *s1, *s2;
+ int n, i;
+ double norm, dx, dy;
+ TriDiagonalMatrix *A; /* The tri-diagonal matrix is saved here. */
+
+ spline = malloc(sizeof(CubicSpline) * nPoints);
+ if (spline == NULL) {
+ return NULL;
+ }
+ A = malloc(sizeof(TriDiagonalMatrix) * nPoints);
+ if (A == NULL) {
+ free(spline);
+ return NULL;
+ }
+ /*
+ * Calculate first differences in (dxdt2[i], y[i]) and interval lengths
+ * in dist[i]:
+ */
+ s1 = spline;
+ for (i = 0; i < nPoints - 1; i++) {
+ s1->x = points[i+1].x - points[i].x;
+ s1->y = points[i+1].y - points[i].y;
+
+ /*
+ * The Norm of a linear stroke is calculated in "normal coordinates"
+ * and used as interval length:
+ */
+ dx = s1->x / unitX;
+ dy = s1->y / unitY;
+ s1->t = sqrt(dx * dx + dy * dy);
+
+ s1->x /= s1->t; /* first difference, with unit norm: */
+ s1->y /= s1->t; /* || (dxdt2[i], y[i]) || = 1 */
+ s1++;
+ }
+
+ /*
+ * Setup linear System: Ax = b
+ */
+ n = nPoints - 2; /* Without first and last point */
+ if (isClosed) {
+ /* First and last points must be equal for CLOSED_CONTOURs */
+ spline[nPoints - 1].t = spline[0].t;
+ spline[nPoints - 1].x = spline[0].x;
+ spline[nPoints - 1].y = spline[0].y;
+ n++; /* Add last point (= first point) */
+ }
+ s1 = spline, s2 = s1 + 1;
+ for (i = 0; i < n; i++) {
+ /* Matrix A, mainly tridiagonal with cyclic second index
+ ("j = j+n mod n")
+ */
+ A[i][0] = s1->t; /* Off-diagonal element A_{i,i-1} */
+ A[i][1] = 2.0 * (s1->t + s2->t); /* A_{i,i} */
+ A[i][2] = s2->t; /* Off-diagonal element A_{i,i+1} */
+
+ /* Right side b_x and b_y */
+ s1->x = (s2->x - s1->x) * 6.0;
+ s1->y = (s2->y - s1->y) * 6.0;
+
+ /*
+ * If the linear stroke shows a cusp of more than 90 degree,
+ * the right side is reduced to avoid oscillations in the
+ * spline:
+ */
+ /*
+ * The Norm of a linear stroke is calculated in "normal coordinates"
+ * and used as interval length:
+ */
+ dx = s1->x / unitX;
+ dy = s1->y / unitY;
+ norm = sqrt(dx * dx + dy * dy) / 8.5;
+ if (norm > 1.0) {
+ /* The first derivative will not be continuous */
+ s1->x /= norm;
+ s1->y /= norm;
+ }
+ s1++, s2++;
+ }
+
+ if (!isClosed) {
+ /* Third derivative is set to zero at both ends */
+ A[0][1] += A[0][0]; /* A_{0,0} */
+ A[0][0] = 0.0; /* A_{0,n-1} */
+ A[n-1][1] += A[n-1][2]; /* A_{n-1,n-1} */
+ A[n-1][2] = 0.0; /* A_{n-1,0} */
+ }
+ /* Solve linear systems for dxdt2[] and y[] */
+
+ if (SolveCubic1(A, n)) { /* Cholesky decomposition */
+ SolveCubic2(A, spline, n); /* A * dxdt2 = b_x */
+ } else { /* Should not happen, but who knows ... */
+ free(A);
+ free(spline);
+ return NULL;
+ }
+ /* Shift all second derivatives one place right and update the ends. */
+ s2 = spline + n, s1 = s2 - 1;
+ for (/* empty */; s2 > spline; s2--, s1--) {
+ s2->x = s1->x;
+ s2->y = s1->y;
+ }
+ if (isClosed) {
+ spline[0].x = spline[n].x;
+ spline[0].y = spline[n].y;
+ } else {
+ /* Third derivative is 0.0 for the first and last interval. */
+ spline[0].x = spline[1].x;
+ spline[0].y = spline[1].y;
+ spline[n + 1].x = spline[n].x;
+ spline[n + 1].y = spline[n].y;
+ }
+ free( A);
+ return spline;
+}
+
+
+/*
+ * Calculate interpolated values of the spline function (defined via p_cntr
+ * and the second derivatives dxdt2[] and dydt2[]). The number of tabulated
+ * values is n. On an equidistant grid n_intpol values are calculated.
+ */
+static int
+CubicEval(Point2d *origPts, int nOrigPts, Point2d *intpPts, int nIntpPts,
+ CubicSpline *spline)
+{
+ double t, tSkip, tMax;
+ Point2d q;
+ int i, j, count;
+
+ /* Sum the lengths of all the segments (intervals). */
+ tMax = 0.0;
+ for (i = 0; i < nOrigPts - 1; i++) {
+ tMax += spline[i].t;
+ }
+
+ /* Need a better way of doing this... */
+
+ /* The distance between interpolated points */
+ tSkip = (1. - 1e-7) * tMax / (nIntpPts - 1);
+
+ t = 0.0; /* Spline parameter value. */
+ q = origPts[0];
+ count = 0;
+
+ intpPts[count++] = q; /* First point. */
+ t += tSkip;
+
+ for (i = 0, j = 1; j < nOrigPts; i++, j++) {
+ Point2d p;
+ double d, hx, dx0, dx01, hy, dy0, dy01;
+
+ d = spline[i].t; /* Interval length */
+ p = q;
+ q = origPts[i+1];
+ hx = (q.x - p.x) / d;
+ hy = (q.y - p.y) / d;
+ dx0 = (spline[j].x + 2 * spline[i].x) / 6.0;
+ dy0 = (spline[j].y + 2 * spline[i].y) / 6.0;
+ dx01 = (spline[j].x - spline[i].x) / (6.0 * d);
+ dy01 = (spline[j].y - spline[i].y) / (6.0 * d);
+ while (t <= spline[i].t) { /* t in current interval ? */
+ p.x += t * (hx + (t - d) * (dx0 + t * dx01));
+ p.y += t * (hy + (t - d) * (dy0 + t * dy01));
+ intpPts[count++] = p;
+ t += tSkip;
+ }
+ /* Parameter t relative to start of next interval */
+ t -= spline[i].t;
+ }
+ return count;
+}
+
+/*
+ * Generate a cubic spline curve through the points (x_i,y_i) which are
+ * stored in the linked list p_cntr.
+ * The spline is defined as a 2d-function s(t) = (x(t),y(t)), where the
+ * parameter t is the length of the linear stroke.
+ */
+int
+Blt_NaturalParametricSpline(Point2d *origPts, int nOrigPts, Region2d *extsPtr,
+ int isClosed, Point2d *intpPts, int nIntpPts)
+{
+ double unitX, unitY; /* To define norm (x,y)-plane */
+ CubicSpline *spline;
+ int result;
+
+ if (nOrigPts < 3) {
+ return 0;
+ }
+ if (isClosed) {
+ origPts[nOrigPts].x = origPts[0].x;
+ origPts[nOrigPts].y = origPts[0].y;
+ nOrigPts++;
+ }
+ /* Width and height of the grid is used at unit length (2d-norm) */
+ unitX = extsPtr->right - extsPtr->left;
+ unitY = extsPtr->bottom - extsPtr->top;
+
+ if (unitX < FLT_EPSILON) {
+ unitX = FLT_EPSILON;
+ }
+ if (unitY < FLT_EPSILON) {
+ unitY = FLT_EPSILON;
+ }
+ /* Calculate parameters for cubic spline:
+ * t = arc length of interval.
+ * dxdt2 = second derivatives of x with respect to t,
+ * dydt2 = second derivatives of y with respect to t,
+ */
+ spline = CubicSlopes(origPts, nOrigPts, isClosed, unitX, unitY);
+ if (spline == NULL) {
+ return 0;
+ }
+ result= CubicEval(origPts, nOrigPts, intpPts, nIntpPts, spline);
+ free(spline);
+ return result;
+}
+
+static INLINE void
+CatromCoeffs(Point2d *p, Point2d *a, Point2d *b, Point2d *c, Point2d *d)
+{
+ a->x = -p[0].x + 3.0 * p[1].x - 3.0 * p[2].x + p[3].x;
+ b->x = 2.0 * p[0].x - 5.0 * p[1].x + 4.0 * p[2].x - p[3].x;
+ c->x = -p[0].x + p[2].x;
+ d->x = 2.0 * p[1].x;
+ a->y = -p[0].y + 3.0 * p[1].y - 3.0 * p[2].y + p[3].y;
+ b->y = 2.0 * p[0].y - 5.0 * p[1].y + 4.0 * p[2].y - p[3].y;
+ c->y = -p[0].y + p[2].y;
+ d->y = 2.0 * p[1].y;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ParametricCatromSpline --
+ *
+ * Computes a spline based upon the data points, returning a new (larger)
+ * coordinate array of points.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_CatromParametricSpline(Point2d *points, int nPoints, Point2d *intpPts,
+ int nIntpPts)
+{
+ int i;
+ Point2d *origPts;
+ double t;
+ int interval;
+ Point2d a, b, c, d;
+
+ assert(nPoints > 0);
+
+ /*
+ * The spline is computed in screen coordinates instead of data points so
+ * that we can select the abscissas of the interpolated points from each
+ * pixel horizontally across the plotting area.
+ */
+ origPts = malloc((nPoints + 4) * sizeof(Point2d));
+ memcpy(origPts + 1, points, sizeof(Point2d) * nPoints);
+
+ origPts[0] = origPts[1];
+ origPts[nPoints + 2] = origPts[nPoints + 1] = origPts[nPoints];
+
+ for (i = 0; i < nIntpPts; i++) {
+ interval = (int)intpPts[i].x;
+ t = intpPts[i].y;
+ assert(interval < nPoints);
+ CatromCoeffs(origPts + interval, &a, &b, &c, &d);
+ intpPts[i].x = (d.x + t * (c.x + t * (b.x + t * a.x))) / 2.0;
+ intpPts[i].y = (d.y + t * (c.y + t * (b.y + t * a.y))) / 2.0;
+ }
+ free(origPts);
+ return 1;
+}
diff --git a/tlt3.0/bltSpline.h b/tlt3.0/bltSpline.h
new file mode 100644
index 0000000..a9553e2
--- /dev/null
+++ b/tlt3.0/bltSpline.h
@@ -0,0 +1,43 @@
+/*
+ * bltSpline.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_SPLINE_H
+#define _BLT_SPLINE_H
+
+#include "bltInt.h"
+
+extern int Blt_NaturalSpline (Point2d *origPts, int nOrigPts, Point2d *intpPts,
+ int nIntpPts);
+
+extern int Blt_QuadraticSpline (Point2d *origPts, int nOrigPts,
+ Point2d *intpPts, int nIntpPts);
+
+extern int Blt_NaturalParametricSpline (Point2d *origPts, int nOrigPts,
+ Region2d *extsPtr, int isClosed, Point2d *intpPts, int nIntpPts);
+
+extern int Blt_CatromParametricSpline (Point2d *origPts, int nOrigPts,
+ Point2d *intpPts, int nIntpPts);
+
+#endif
diff --git a/tlt3.0/bltSwitch.c b/tlt3.0/bltSwitch.c
new file mode 100644
index 0000000..8c4fee0
--- /dev/null
+++ b/tlt3.0/bltSwitch.c
@@ -0,0 +1,538 @@
+/*
+ * bltSwitch.c --
+ *
+ * This module implements command/argument switch parsing procedures for the
+ * BLT toolkit.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdarg.h>
+
+#include "bltInt.h"
+#include "bltSwitch.h"
+
+static void
+DoHelp(Tcl_Interp *interp, Blt_SwitchSpec *specs)
+{
+ Tcl_DString ds;
+ Blt_SwitchSpec *sp;
+
+ Tcl_DStringInit(&ds);
+ Tcl_DStringAppend(&ds, "following switches are available:", -1);
+ for (sp = specs; sp->type != BLT_SWITCH_END; sp++) {
+ Tcl_DStringAppend(&ds, "\n ", 4);
+ Tcl_DStringAppend(&ds, sp->switchName, -1);
+ Tcl_DStringAppend(&ds, " ", 1);
+ Tcl_DStringAppend(&ds, sp->help, -1);
+ }
+ Tcl_AppendResult(interp, Tcl_DStringValue(&ds), (char *)NULL);
+ Tcl_DStringFree(&ds);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindSwitchSpec --
+ *
+ * Search through a table of configuration specs, looking for one that
+ * matches a given argvName.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL if
+ * nothing matched. In that case an error message is left in the
+ * interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_SwitchSpec *
+FindSwitchSpec(
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Blt_SwitchSpec *specs, /* Pointer to table of configuration
+ * specifications for a widget. */
+ const char *name, /* Name identifying a particular switch. */
+ int length, /* Length of name. */
+ int needFlags, /* Flags that must be present in matching
+ * entry. */
+ int hateFlags) /* Flags that must NOT be present in matching
+ * entry. */
+{
+ Blt_SwitchSpec *sp;
+ char c; /* First character of current argument. */
+ Blt_SwitchSpec *matchPtr; /* Matching spec, or NULL. */
+
+ c = name[1];
+ matchPtr = NULL;
+ for (sp = specs; sp->type != BLT_SWITCH_END; sp++) {
+ if (sp->switchName == NULL) {
+ continue;
+ }
+ if (((sp->flags & needFlags) != needFlags) || (sp->flags & hateFlags)) {
+ continue;
+ }
+ if ((sp->switchName[1] != c) ||
+ (strncmp(sp->switchName, name, length) != 0)) {
+ continue;
+ }
+ if (sp->switchName[length] == '\0') {
+ return sp; /* Stop on a perfect match. */
+ }
+ if (matchPtr != NULL) {
+ Tcl_AppendResult(interp, "ambiguous switch \"", name, "\"\n",
+ (char *) NULL);
+ DoHelp(interp, specs);
+ return NULL;
+ }
+ matchPtr = sp;
+ }
+ if (strcmp(name, "-help") == 0) {
+ DoHelp(interp, specs);
+ return NULL;
+ }
+ if (matchPtr == NULL) {
+ Tcl_AppendResult(interp, "unknown switch \"", name, "\"\n",
+ (char *)NULL);
+ DoHelp(interp, specs);
+ return NULL;
+ }
+ return matchPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DoSwitch --
+ *
+ * This procedure applies a single configuration switch to a widget
+ * record.
+ *
+ * Results:
+ * A standard TCL return value.
+ *
+ * Side effects:
+ * WidgRec is modified as indicated by specPtr and value. The old value
+ * is recycled, if that is appropriate for the value type.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+DoSwitch(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Blt_SwitchSpec *sp, /* Specifier to apply. */
+ Tcl_Obj *objPtr, /* Value to use to fill in widgRec. */
+ void *record) /* Record whose fields are to be modified.
+ * Values must be properly initialized. */
+{
+ do {
+ char *ptr;
+
+ ptr = (char *)record + sp->offset;
+ switch (sp->type) {
+ case BLT_SWITCH_BOOLEAN:
+ {
+ int bool;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (sp->mask > 0) {
+ if (bool) {
+ *((int *)ptr) |= sp->mask;
+ } else {
+ *((int *)ptr) &= ~sp->mask;
+ }
+ } else {
+ *((int *)ptr) = bool;
+ }
+ }
+ break;
+
+ case BLT_SWITCH_DOUBLE:
+ if (Tcl_GetDoubleFromObj(interp, objPtr, (double *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_SWITCH_OBJ:
+ Tcl_IncrRefCount(objPtr);
+ *(Tcl_Obj **)ptr = objPtr;
+ break;
+
+ case BLT_SWITCH_FLOAT:
+ {
+ double value;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(float *)ptr = (float)value;
+ }
+ break;
+
+ case BLT_SWITCH_INT:
+ if (Tcl_GetIntFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_SWITCH_INT_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+ case BLT_SWITCH_INT_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+ case BLT_SWITCH_LIST:
+ {
+ int argc;
+
+ if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &argc,
+ (const char ***)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ break;
+
+ case BLT_SWITCH_LONG:
+ if (Tcl_GetLongFromObj(interp, objPtr, (long *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_SWITCH_LONG_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_SWITCH_LONG_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS, &value)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_SWITCH_STRING:
+ {
+ char *value;
+
+ value = Tcl_GetString(objPtr);
+ value = (*value == '\0') ? NULL : Blt_Strdup(value);
+ if (*(char **)ptr != NULL) {
+ free(*(char **)ptr);
+ }
+ *(char **)ptr = value;
+ }
+ break;
+
+ case BLT_SWITCH_CUSTOM:
+ assert(sp->customPtr != NULL);
+ if ((*sp->customPtr->parseProc)(sp->customPtr->clientData, interp,
+ sp->switchName, objPtr, (char *)record, sp->offset, sp->flags)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ default:
+ Tcl_AppendResult(interp, "bad switch table: unknown type \"",
+ Blt_Itoa(sp->type), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ sp++;
+ } while ((sp->switchName == NULL) && (sp->type != BLT_SWITCH_END));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ParseSwitches --
+ *
+ * Process command-line switches to fill in fields of a record with
+ * resources and other parameters.
+ *
+ * Results:
+ * Returns the number of arguments comsumed by parsing the command line.
+ * If an error occurred, -1 will be returned and an error messages can be
+ * found as the interpreter result.
+ *
+ * Side effects:
+ * The fields of widgRec get filled in with information from argc/argv.
+ * Old information in widgRec's fields gets recycled.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ParseSwitches(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Blt_SwitchSpec *specs, /* Describes legal switches. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const *objv, /* Command-line switches. */
+ void *record, /* Record whose fields are to be modified.
+ * Values must be properly initialized. */
+ int flags) /* Used to specify additional flags that must
+ * be present in switch specs for them to be
+ * considered. */
+{
+ Blt_SwitchSpec *sp;
+ int count;
+ int needFlags; /* Specs must contain this set of flags or
+ * else they are not considered. */
+ int hateFlags; /* If a spec contains any bits here, it's not
+ * considered. */
+
+ needFlags = flags & ~(BLT_SWITCH_USER_BIT - 1);
+ hateFlags = 0;
+
+ /*
+ * Pass 1: Clear the change flags on all the specs so that we
+ * can check it later.
+ */
+ for (sp = specs; sp->type != BLT_SWITCH_END; sp++) {
+ sp->flags &= ~BLT_SWITCH_SPECIFIED;
+ }
+ /*
+ * Pass 2: Process the arguments that match entries in the specs.
+ * It's an error if the argument doesn't match anything.
+ */
+ for (count = 0; count < objc; count++) {
+ char *arg;
+ int length;
+
+ arg = Tcl_GetStringFromObj(objv[count], &length);
+ if (flags & BLT_SWITCH_OBJV_PARTIAL) {
+ /*
+ * If the argument doesn't start with a '-' (not a switch) or is
+ * '--', stop processing and return the number of arguments
+ * comsumed.
+ */
+ if (arg[0] != '-') {
+ return count;
+ }
+ if ((arg[1] == '-') && (arg[2] == '\0')) {
+ return count + 1; /* include the "--" in the count. */
+ }
+ }
+ sp = FindSwitchSpec(interp, specs, arg, length, needFlags, hateFlags);
+ if (sp == NULL) {
+ return -1;
+ }
+ if (sp->type == BLT_SWITCH_BITMASK) {
+ char *ptr;
+
+ ptr = (char *)record + sp->offset;
+ *((int *)ptr) |= sp->mask;
+ } else if (sp->type == BLT_SWITCH_BITMASK_INVERT) {
+ char *ptr;
+
+ ptr = (char *)record + sp->offset;
+ *((int *)ptr) &= ~sp->mask;
+ } else if (sp->type == BLT_SWITCH_VALUE) {
+ char *ptr;
+
+ ptr = (char *)record + sp->offset;
+ *((int *)ptr) = sp->mask;
+ } else {
+ count++;
+ if (count == objc) {
+ Tcl_AppendResult(interp, "value for \"", arg, "\" missing",
+ (char *) NULL);
+ return -1;
+ }
+ if (DoSwitch(interp, sp, objv[count], record) != TCL_OK) {
+ char msg[200];
+
+ sprintf_s(msg, 200, "\n (processing \"%.40s\" switch)",
+ sp->switchName);
+ Tcl_AddErrorInfo(interp, msg);
+ return -1;
+ }
+ }
+ sp->flags |= BLT_SWITCH_SPECIFIED;
+ }
+ return count;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeSwitches --
+ *
+ * Free up all resources associated with switches.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+void
+Blt_FreeSwitches(
+ Blt_SwitchSpec *specs, /* Describes legal switches. */
+ void *record, /* Record whose fields contain current values
+ * for switches. */
+ int needFlags) /* Used to specify additional flags that must
+ * be present in config specs for them to be
+ * considered. */
+{
+ Blt_SwitchSpec *sp;
+
+ for (sp = specs; sp->type != BLT_SWITCH_END; sp++) {
+ if ((sp->flags & needFlags) == needFlags) {
+ char *ptr;
+
+ ptr = (char *)record + sp->offset;
+ switch (sp->type) {
+ case BLT_SWITCH_STRING:
+ case BLT_SWITCH_LIST:
+ if (*((char **) ptr) != NULL) {
+ free(*((char **) ptr));
+ *((char **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_SWITCH_OBJ:
+ if (*((Tcl_Obj **) ptr) != NULL) {
+ Tcl_DecrRefCount(*((Tcl_Obj **)ptr));
+ *((Tcl_Obj **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_SWITCH_CUSTOM:
+ assert(sp->customPtr != NULL);
+ if ((*(char **)ptr != NULL) &&
+ (sp->customPtr->freeProc != NULL)) {
+ (*sp->customPtr->freeProc)((char *)record, sp->offset,
+ sp->flags);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_SwitchModified --
+ *
+ * Given the configuration specifications and one or more switch patterns
+ * (terminated by a NULL), indicate if any of the matching switches has
+ * been reset.
+ *
+ * Results:
+ * Returns 1 if one of the switches have changed, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_SwitchChanged TCL_VARARGS_DEF(Blt_SwitchSpec *, arg1)
+{
+ va_list argList;
+ Blt_SwitchSpec *specs;
+ Blt_SwitchSpec *sp;
+ char *switchName;
+
+ specs = TCL_VARARGS_START(Blt_SwitchSpec *, arg1, argList);
+ while ((switchName = va_arg(argList, char *)) != NULL) {
+ for (sp = specs; sp->type != BLT_SWITCH_END; sp++) {
+ if ((Tcl_StringMatch(sp->switchName, switchName)) &&
+ (sp->flags & BLT_SWITCH_SPECIFIED)) {
+ va_end(argList);
+ return 1;
+ }
+ }
+ }
+ va_end(argList);
+ return 0;
+}
+
+int
+Blt_ExprDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *valuePtr)
+{
+ /* First try to extract the value as a double precision number. */
+ if (Tcl_GetDoubleFromObj((Tcl_Interp *)NULL, objPtr, valuePtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ /* Then try to parse it as an expression. */
+ if (Tcl_ExprDouble(interp, Tcl_GetString(objPtr), valuePtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+int
+Blt_ExprIntFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ int *valuePtr)
+{
+ long lvalue;
+
+ /* First try to extract the value as a simple integer. */
+ if (Tcl_GetIntFromObj((Tcl_Interp *)NULL, objPtr, valuePtr) == TCL_OK) {
+ return TCL_OK;
+ }
+ /* Otherwise try to parse it as an expression. */
+ if (Tcl_ExprLong(interp, Tcl_GetString(objPtr), &lvalue) == TCL_OK) {
+ *valuePtr = lvalue;
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
diff --git a/tlt3.0/bltSwitch.h b/tlt3.0/bltSwitch.h
new file mode 100644
index 0000000..a075d0b
--- /dev/null
+++ b/tlt3.0/bltSwitch.h
@@ -0,0 +1,134 @@
+
+/*
+ * bltSwitch.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef BLT_SWITCH_H
+#define BLT_SWITCH_H
+
+# include <stddef.h>
+
+#ifndef Blt_Offset
+#ifdef offsetof
+#define Blt_Offset(type, field) ((int) offsetof(type, field))
+#else
+#define Blt_Offset(type, field) ((int) ((char *) &((type *) 0)->field))
+#endif
+#endif /* Blt_Offset */
+
+typedef int (Blt_SwitchParseProc)(ClientData clientData, Tcl_Interp *interp,
+ const char *switchName, Tcl_Obj *valueObjPtr, char *record, int offset,
+ int flags);
+typedef void (Blt_SwitchFreeProc)(char *record, int offset, int flags);
+
+typedef struct {
+ Blt_SwitchParseProc *parseProc; /* Procedure to parse a switch
+ * value and store it in its *
+ * converted form in the data *
+ * record. */
+
+ Blt_SwitchFreeProc *freeProc; /* Procedure to free a switch. */
+
+ ClientData clientData; /* Arbitrary one-word value used by
+ * switch parser, passed to
+ * parseProc. */
+} Blt_SwitchCustom;
+
+
+/*
+ * Type values for Blt_SwitchSpec structures. See the user
+ * documentation for details.
+ */
+typedef enum {
+ BLT_SWITCH_BOOLEAN,
+ BLT_SWITCH_DOUBLE,
+ BLT_SWITCH_BITMASK,
+ BLT_SWITCH_BITMASK_INVERT,
+ BLT_SWITCH_FLOAT,
+ BLT_SWITCH_INT,
+ BLT_SWITCH_INT_NNEG,
+ BLT_SWITCH_INT_POS,
+ BLT_SWITCH_LIST,
+ BLT_SWITCH_LONG,
+ BLT_SWITCH_LONG_NNEG,
+ BLT_SWITCH_LONG_POS,
+ BLT_SWITCH_OBJ,
+ BLT_SWITCH_STRING,
+ BLT_SWITCH_VALUE,
+ BLT_SWITCH_CUSTOM,
+ BLT_SWITCH_END
+} Blt_SwitchTypes;
+
+
+typedef struct {
+ Blt_SwitchTypes type; /* Type of option, such as
+ * BLT_SWITCH_COLOR; see definitions
+ * below. Last option in table must
+ * have type BLT_SWITCH_END. */
+
+ const char *switchName; /* Switch used to specify option in
+ * argv. NULL means this spec is part
+ * of a group. */
+
+ const char *help; /* Help string. */
+ int offset; /* Where in widget record to store
+ * value; use Blt_Offset macro to
+ * generate values for this. */
+
+ int flags; /* Any combination of the values
+ * defined below. */
+
+ unsigned int mask;
+
+ Blt_SwitchCustom *customPtr; /* If type is BLT_SWITCH_CUSTOM then
+ * this is a pointer to info about how
+ * to parse and print the option.
+ * Otherwise it is irrelevant. */
+} Blt_SwitchSpec;
+
+#define BLT_SWITCH_DEFAULTS (0)
+#define BLT_SWITCH_ARGV_PARTIAL (1<<1)
+#define BLT_SWITCH_OBJV_PARTIAL (1<<1)
+
+/*
+ * Possible flag values for Blt_SwitchSpec structures. Any bits at or
+ * above BLT_SWITCH_USER_BIT may be used by clients for selecting
+ * certain entries.
+ */
+#define BLT_SWITCH_NULL_OK (1<<0)
+#define BLT_SWITCH_DONT_SET_DEFAULT (1<<3)
+#define BLT_SWITCH_SPECIFIED (1<<4)
+#define BLT_SWITCH_USER_BIT (1<<8)
+
+extern int Blt_ParseSwitches(Tcl_Interp *interp, Blt_SwitchSpec *specPtr,
+ int objc, Tcl_Obj *const *objv, void *rec, int flags);
+
+extern void Blt_FreeSwitches(Blt_SwitchSpec *specs, void *rec, int flags);
+
+extern int Blt_SwitchChanged TCL_VARARGS(Blt_SwitchSpec *, specs);
+
+#endif /* BLT_SWITCH_H */
diff --git a/tlt3.0/bltText.c b/tlt3.0/bltText.c
new file mode 100644
index 0000000..eff55e8
--- /dev/null
+++ b/tlt3.0/bltText.c
@@ -0,0 +1,1320 @@
+/*
+ * bltText.c --
+ *
+ * This module implements multi-line, rotate-able text for the BLT toolkit.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <X11/Xutil.h>
+
+#include <tkPort.h>
+#include <tkInt.h>
+#include <tk3d.h>
+
+#include "bltInt.h"
+#include "bltMath.h"
+#include "bltHash.h"
+#include "bltImage.h"
+#include "bltBitmap.h"
+#include "bltFont.h"
+#include "bltText.h"
+#include "bltBgStyle.h"
+
+static Blt_HashTable bitmapGCTable;
+static int initialized;
+
+GC
+Blt_GetBitmapGC(Tk_Window tkwin)
+{
+ int isNew;
+ GC gc;
+ Display *display;
+ Blt_HashEntry *hPtr;
+
+ if (!initialized) {
+ Blt_InitHashTable(&bitmapGCTable, BLT_ONE_WORD_KEYS);
+ initialized = TRUE;
+ }
+ display = Tk_Display(tkwin);
+ hPtr = Blt_CreateHashEntry(&bitmapGCTable, (char *)display, &isNew);
+ if (isNew) {
+ Pixmap bitmap;
+ XGCValues gcValues;
+ unsigned long gcMask;
+ Window root;
+
+ root = Tk_RootWindow(tkwin);
+ bitmap = Tk_GetPixmap(display, root, 1, 1, 1);
+ gcValues.foreground = gcValues.background = 0;
+ gcMask = (GCForeground | GCBackground);
+ gc = Blt_GetPrivateGCFromDrawable(display, bitmap, gcMask, &gcValues);
+ Tk_FreePixmap(display, bitmap);
+ Blt_SetHashValue(hPtr, gc);
+ } else {
+ gc = (GC)Blt_GetHashValue(hPtr);
+ }
+ return gc;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetTextExtents --
+ *
+ * Get the extents of a possibly multiple-lined text string.
+ *
+ * Results:
+ * Returns via *widthPtr* and *heightPtr* the dimensions of the text
+ * string.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_GetTextExtents(
+ Blt_Font font,
+ int leader,
+ const char *text, /* Text string to be measured. */
+ int textLen, /* Length of the text. If -1, indicates that
+ * text is an ASCIZ string that the length
+ * should be computed with strlen. */
+ unsigned int *widthPtr,
+ unsigned int *heightPtr)
+{
+ unsigned int lineHeight;
+
+ if (text == NULL) {
+ return; /* NULL string? */
+ }
+ {
+ Blt_FontMetrics fm;
+
+ Blt_GetFontMetrics(font, &fm);
+ lineHeight = fm.linespace;
+ }
+ if (textLen < 0) {
+ textLen = strlen(text);
+ }
+ {
+ unsigned int lineLen; /* # of characters on each line */
+ const char *p, *pend;
+ const char *line;
+ unsigned int maxWidth, maxHeight;
+
+ maxWidth = maxHeight = 0;
+ lineLen = 0;
+ for (p = line = text, pend = text + textLen; p < pend; p++) {
+ if (*p == '\n') {
+ if (lineLen > 0) {
+ unsigned int lineWidth;
+
+ lineWidth = Blt_TextWidth(font, line, lineLen);
+ if (lineWidth > maxWidth) {
+ maxWidth = lineWidth;
+ }
+ }
+ maxHeight += lineHeight;
+ line = p + 1; /* Point to the start of the next line. */
+ lineLen = 0; /* Reset counter to indicate the start of a
+ * new line. */
+ continue;
+ }
+ lineLen++;
+ }
+ if ((lineLen > 0) && (*(p - 1) != '\n')) {
+ unsigned int lineWidth;
+
+ maxHeight += lineHeight;
+ lineWidth = Blt_TextWidth(font, line, lineLen);
+ if (lineWidth > maxWidth) {
+ maxWidth = lineWidth;
+ }
+ }
+ *widthPtr = maxWidth;
+ *heightPtr = maxHeight;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ts_GetExtents --
+ *
+ * Get the extents of a possibly multiple-lined text string.
+ *
+ * Results:
+ * Returns via *widthPtr* and *heightPtr* the dimensions of
+ * the text string.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ts_GetExtents(TextStyle *tsPtr, const char *text, unsigned int *widthPtr,
+ unsigned int *heightPtr)
+{
+
+ if (text == NULL) {
+ *widthPtr = *heightPtr = 0;
+ } else {
+ unsigned int w, h;
+
+ Blt_GetTextExtents(tsPtr->font, tsPtr->leader, text, -1, &w, &h);
+ *widthPtr = w + PADDING(tsPtr->xPad);
+ *heightPtr = h + PADDING(tsPtr->yPad);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetBoundingBox
+ *
+ * Computes the dimensions of the bounding box surrounding a rectangle
+ * rotated about its center. If pointArr isn't NULL, the coordinates of
+ * the rotated rectangle are also returned.
+ *
+ * The dimensions are determined by rotating the rectangle, and doubling
+ * the maximum x-coordinate and y-coordinate.
+ *
+ * w = 2 * maxX, h = 2 * maxY
+ *
+ * Since the rectangle is centered at 0,0, the coordinates of the
+ * bounding box are (-w/2,-h/2 w/2,-h/2, w/2,h/2 -w/2,h/2).
+ *
+ * 0 ------- 1
+ * | |
+ * | x |
+ * | |
+ * 3 ------- 2
+ *
+ * Results:
+ * The width and height of the bounding box containing the rotated
+ * rectangle are returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_GetBoundingBox(
+ int width, int height, /* Unrotated region */
+ float angle, /* Rotation of box */
+ double *rotWidthPtr,
+ double *rotHeightPtr, /* (out) Bounding box region */
+ Point2d *bbox) /* (out) Points of the rotated box */
+{
+ int i;
+ double sinTheta, cosTheta;
+ double radians;
+ double xMax, yMax;
+ double x, y;
+ Point2d corner[4];
+
+ angle = fmod(angle, 360.0);
+ if (fmod(angle, (double)90.0) == 0.0) {
+ int ll, ur, ul, lr;
+ double rotWidth, rotHeight;
+ int quadrant;
+
+ /* Handle right-angle rotations specially. */
+
+ quadrant = (int)(angle / 90.0);
+ switch (quadrant) {
+ case ROTATE_270: /* 270 degrees */
+ ul = 3, ur = 0, lr = 1, ll = 2;
+ rotWidth = (double)height;
+ rotHeight = (double)width;
+ break;
+ case ROTATE_90: /* 90 degrees */
+ ul = 1, ur = 2, lr = 3, ll = 0;
+ rotWidth = (double)height;
+ rotHeight = (double)width;
+ break;
+ case ROTATE_180: /* 180 degrees */
+ ul = 2, ur = 3, lr = 0, ll = 1;
+ rotWidth = (double)width;
+ rotHeight = (double)height;
+ break;
+ default:
+ case ROTATE_0: /* 0 degrees */
+ ul = 0, ur = 1, lr = 2, ll = 3;
+ rotWidth = (double)width;
+ rotHeight = (double)height;
+ break;
+ }
+ if (bbox != NULL) {
+ x = rotWidth * 0.5;
+ y = rotHeight * 0.5;
+ bbox[ll].x = bbox[ul].x = -x;
+ bbox[ur].y = bbox[ul].y = -y;
+ bbox[lr].x = bbox[ur].x = x;
+ bbox[ll].y = bbox[lr].y = y;
+ }
+ *rotWidthPtr = rotWidth;
+ *rotHeightPtr = rotHeight;
+ return;
+ }
+ /* Set the four corners of the rectangle whose center is the origin. */
+ corner[1].x = corner[2].x = (double)width * 0.5;
+ corner[0].x = corner[3].x = -corner[1].x;
+ corner[2].y = corner[3].y = (double)height * 0.5;
+ corner[0].y = corner[1].y = -corner[2].y;
+
+ radians = (-angle / 180.0) * M_PI;
+ sinTheta = sin(radians), cosTheta = cos(radians);
+ xMax = yMax = 0.0;
+
+ /* Rotate the four corners and find the maximum X and Y coordinates */
+
+ for (i = 0; i < 4; i++) {
+ x = (corner[i].x * cosTheta) - (corner[i].y * sinTheta);
+ y = (corner[i].x * sinTheta) + (corner[i].y * cosTheta);
+ if (x > xMax) {
+ xMax = x;
+ }
+ if (y > yMax) {
+ yMax = y;
+ }
+ if (bbox != NULL) {
+ bbox[i].x = x;
+ bbox[i].y = y;
+ }
+ }
+
+ /*
+ * By symmetry, the width and height of the bounding box are twice the
+ * maximum x and y coordinates.
+ */
+ *rotWidthPtr = xMax + xMax;
+ *rotHeightPtr = yMax + yMax;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_TranslateAnchor --
+ *
+ * Translate the coordinates of a given bounding box based upon the
+ * anchor specified. The anchor indicates where the given x-y position
+ * is in relation to the bounding box.
+ *
+ * nw --- n --- ne
+ * | |
+ * w center e
+ * | |
+ * sw --- s --- se
+ *
+ * The coordinates returned are translated to the origin of the bounding
+ * box (suitable for giving to XCopyArea, XCopyPlane, etc.)
+ *
+ * Results:
+ * The translated coordinates of the bounding box are returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_TranslateAnchor(
+ int x, int y, /* Window coordinates of anchor */
+ int w, int h, /* Extents of the bounding box */
+ Tk_Anchor anchor, /* Direction of the anchor */
+ int *xPtr, int *yPtr)
+{
+ switch (anchor) {
+ case TK_ANCHOR_NW: /* Upper left corner */
+ break;
+ case TK_ANCHOR_W: /* Left center */
+ y -= (h / 2);
+ break;
+ case TK_ANCHOR_SW: /* Lower left corner */
+ y -= h;
+ break;
+ case TK_ANCHOR_N: /* Top center */
+ x -= (w / 2);
+ break;
+ case TK_ANCHOR_CENTER: /* Center */
+ x -= (w / 2);
+ y -= (h / 2);
+ break;
+ case TK_ANCHOR_S: /* Bottom center */
+ x -= (w / 2);
+ y -= h;
+ break;
+ case TK_ANCHOR_NE: /* Upper right corner */
+ x -= w;
+ break;
+ case TK_ANCHOR_E: /* Right center */
+ x -= w;
+ y -= (h / 2);
+ break;
+ case TK_ANCHOR_SE: /* Lower right corner */
+ x -= w;
+ y -= h;
+ break;
+ }
+ *xPtr = x;
+ *yPtr = y;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_AnchorPoint --
+ *
+ * Translates a position, using both the dimensions of the bounding box,
+ * and the anchor direction, returning the coordinates of the upper-left
+ * corner of the box. The anchor indicates where the given x-y position
+ * is in relation to the bounding box.
+ *
+ * nw --- n --- ne
+ * | |
+ * w center e
+ * | |
+ * sw --- s --- se
+ *
+ * The coordinates returned are translated to the origin of the bounding
+ * box (suitable for giving to XCopyArea, XCopyPlane, etc.)
+ *
+ * Results:
+ * The translated coordinates of the bounding box are returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+Point2d
+Blt_AnchorPoint(
+ double x, double y, /* Coordinates of anchor. */
+ double w, double h, /* Extents of the bounding box */
+ Tk_Anchor anchor) /* Direction of the anchor */
+{
+ Point2d t;
+
+ switch (anchor) {
+ case TK_ANCHOR_NW: /* Upper left corner */
+ break;
+ case TK_ANCHOR_W: /* Left center */
+ y -= (h * 0.5);
+ break;
+ case TK_ANCHOR_SW: /* Lower left corner */
+ y -= h;
+ break;
+ case TK_ANCHOR_N: /* Top center */
+ x -= (w * 0.5);
+ break;
+ case TK_ANCHOR_CENTER: /* Center */
+ x -= (w * 0.5);
+ y -= (h * 0.5);
+ break;
+ case TK_ANCHOR_S: /* Bottom center */
+ x -= (w * 0.5);
+ y -= h;
+ break;
+ case TK_ANCHOR_NE: /* Upper right corner */
+ x -= w;
+ break;
+ case TK_ANCHOR_E: /* Right center */
+ x -= w;
+ y -= (h * 0.5);
+ break;
+ case TK_ANCHOR_SE: /* Lower right corner */
+ x -= w;
+ y -= h;
+ break;
+ }
+ t.x = x;
+ t.y = y;
+ return t;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ts_CreateLayout --
+ *
+ * Get the extents of a possibly multiple-lined text string.
+ *
+ * Results:
+ * Returns via *widthPtr* and *heightPtr* the dimensions of the text
+ * string.
+ *
+ *---------------------------------------------------------------------------
+ */
+TextLayout *
+Blt_Ts_CreateLayout(const char *text, int textLen, TextStyle *tsPtr)
+{
+ TextFragment *fp;
+ TextLayout *layoutPtr;
+ Blt_FontMetrics fm;
+ int count; /* Count # of characters on each line */
+ int lineHeight;
+ size_t maxHeight, maxWidth;
+ size_t nFrags;
+ int width; /* Running dimensions of the text */
+ const char *p, *endp, *start;
+ int i;
+ size_t size;
+
+ nFrags = 0;
+ endp = text + ((textLen < 0) ? strlen(text) : textLen);
+ for (p = text; p < endp; p++) {
+ if (*p == '\n') {
+ nFrags++;
+ }
+ }
+ if ((p != text) && (*(p - 1) != '\n')) {
+ nFrags++;
+ }
+ size = sizeof(TextLayout) + (sizeof(TextFragment) * (nFrags - 1));
+
+ layoutPtr = calloc(1, size);
+ layoutPtr->nFrags = nFrags;
+
+ nFrags = count = 0;
+ width = maxWidth = 0;
+ maxHeight = tsPtr->padTop;
+ Blt_GetFontMetrics(tsPtr->font, &fm);
+ lineHeight = fm.linespace + tsPtr->leader;
+
+ fp = layoutPtr->fragments;
+ for (p = start = text; p < endp; p++) {
+ if (*p == '\n') {
+ if (count > 0) {
+ width = Blt_TextWidth(tsPtr->font, start, count);
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ } else {
+ width = 0;
+ }
+ fp->width = width;
+ fp->count = count;
+ fp->sy = fp->y = maxHeight + fm.ascent;
+ fp->text = start;
+ maxHeight += lineHeight;
+ fp++;
+ nFrags++;
+ start = p + 1; /* Start the text on the next line */
+ count = 0; /* Reset to indicate the start of a new
+ * line */
+ continue;
+ }
+ count++;
+ }
+
+ if (nFrags < layoutPtr->nFrags) {
+ width = Blt_TextWidth(tsPtr->font, start, count);
+ if (width > maxWidth) {
+ maxWidth = width;
+ }
+ fp->width = width;
+ fp->count = count;
+ fp->sy = fp->y = maxHeight + fm.ascent;
+ fp->text = start;
+ maxHeight += lineHeight;
+ nFrags++;
+ }
+ maxHeight += tsPtr->padBottom;
+ maxWidth += PADDING(tsPtr->xPad);
+ fp = layoutPtr->fragments;
+ for (i = 0; i < nFrags; i++, fp++) {
+ switch (tsPtr->justify) {
+ default:
+ case TK_JUSTIFY_LEFT:
+ /* No offset for left justified text strings */
+ fp->x = fp->sx = tsPtr->padLeft;
+ break;
+ case TK_JUSTIFY_RIGHT:
+ fp->x = fp->sx = (maxWidth - fp->width) - tsPtr->padRight;
+ break;
+ case TK_JUSTIFY_CENTER:
+ fp->x = fp->sx = (maxWidth - fp->width) / 2;
+ break;
+ }
+ }
+ if (tsPtr->underline >= 0) {
+ fp = layoutPtr->fragments;
+ for (i = 0; i < nFrags; i++, fp++) {
+ int first, last;
+
+ first = fp->text - text;
+ last = first + fp->count;
+ if ((tsPtr->underline >= first) && (tsPtr->underline < last)) {
+ layoutPtr->underlinePtr = fp;
+ layoutPtr->underline = tsPtr->underline - first;
+ break;
+ }
+ }
+ }
+ layoutPtr->width = maxWidth;
+ layoutPtr->height = maxHeight - tsPtr->leader;
+ return layoutPtr;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DrawCharsWithEllipsis --
+ *
+ * Draw a string of characters on the screen. Blt_DrawChars()
+ * expands control characters that occur in the string to
+ * \xNN sequences.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets drawn on the screen.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_DrawCharsWithEllipsis(
+ Tk_Window tkwin, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ Blt_Font font, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ int depth,
+ float angle,
+ const char *text, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are
+ * not stripped out, they will be displayed as
+ * regular printing characters. */
+ int textLen, /* # of bytes to draw in text string. */
+ int x, int y, /* Coordinates at which to place origin of
+ * string when drawing. */
+ int maxLength)
+{
+ int elWidth;
+ const char *s, *send;
+ Tcl_DString dString;
+ int nBytes;
+ int accum, threshold;
+
+#if HAVE_UTF
+ Tcl_UniChar ch;
+#endif /* HAVE_UTF */
+ accum = 0;
+ elWidth = Blt_TextWidth(font, "...", 3);
+ if (maxLength < elWidth) {
+ return;
+ }
+ threshold = maxLength - elWidth;
+ Tcl_DStringInit(&dString);
+#if !HAVE_UTF
+ nBytes = 1;
+#endif /* !HAVE_UTF */
+ for (s = text, send = s + textLen; s < send; s += nBytes) {
+#if HAVE_UTF
+ nBytes = Tcl_UtfToUniChar (s, &ch);
+#endif /* HAVE_UTF */
+ accum += Blt_TextWidth(font, s, nBytes);
+ if (accum > threshold) {
+ break;
+ }
+ Tcl_DStringAppend(&dString, s, nBytes);
+ }
+ if (s < send) {
+ Tcl_DStringAppend(&dString, "...", 3);
+ }
+ Blt_DrawChars(Tk_Display(tkwin), drawable, gc, font, depth, angle,
+ Tcl_DStringValue(&dString), Tcl_DStringLength(&dString), x, y);
+ Tcl_DStringFree(&dString);
+}
+
+void
+Blt_DrawLayout(Tk_Window tkwin, Drawable drawable, GC gc, Blt_Font font,
+ int depth, float angle, int x, int y, TextLayout *layoutPtr,
+ int maxLength)
+{
+ TextFragment *fp, *fend;
+ Blt_FontMetrics fm;
+
+ Blt_GetFontMetrics(font, &fm);
+ for (fp = layoutPtr->fragments, fend = fp + layoutPtr->nFrags;
+ fp < fend; fp++) {
+ int sx, sy;
+
+ sx = x + fp->sx, sy = y + fp->sy;
+ if ((maxLength > 0) && ((fp->width + fp->x) > maxLength)) {
+ Blt_DrawCharsWithEllipsis(tkwin, drawable, gc, font, depth, angle,
+ fp->text, fp->count, sx, sy, maxLength - fp->x);
+ } else {
+ Blt_DrawChars(Tk_Display(tkwin), drawable, gc, font, depth, angle,
+ fp->text, fp->count, sx, sy);
+ }
+ }
+ if (layoutPtr->underlinePtr != NULL) {
+ fp = layoutPtr->underlinePtr;
+ Blt_UnderlineChars(Tk_Display(tkwin), drawable, gc, font, fp->text,
+ fp->count, x + fp->sx, y + fp->sy, layoutPtr->underline,
+ layoutPtr->underline + 1, maxLength);
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ts_Bitmap --
+ *
+ * Draw a bitmap, using the the given window coordinates as an anchor for
+ * the text bounding box.
+ *
+ * Results:
+ * Returns the bitmap representing the text string.
+ *
+ * Side Effects:
+ * Bitmap is drawn using the given font and GC in the drawable at the
+ * given coordinates, anchor, and rotation.
+ *
+ *---------------------------------------------------------------------------
+ */
+Pixmap
+Blt_Ts_Bitmap(
+ Tk_Window tkwin,
+ TextLayout *layoutPtr, /* Text string to draw */
+ TextStyle *stylePtr, /* Text attributes: rotation, color,
+ * font, linespacing, justification,
+ * etc. */
+ int *bmWidthPtr,
+ int *bmHeightPtr) /* Extents of rotated text string */
+{
+ Pixmap bitmap;
+ GC gc;
+
+ /* Create a bitmap big enough to contain the text. */
+ bitmap = Tk_GetPixmap(Tk_Display(tkwin), Tk_RootWindow(tkwin),
+ layoutPtr->width, layoutPtr->height, 1);
+ assert(bitmap != None);
+ if (bitmap == None) {
+ return None; /* Can't allocate pixmap. */
+ }
+ gc = Blt_GetBitmapGC(tkwin);
+
+ /* Clear the bitmap. Background is 0. */
+ XSetForeground(Tk_Display(tkwin), gc, 0);
+ XFillRectangle(Tk_Display(tkwin), bitmap, gc, 0, 0, layoutPtr->width,
+ layoutPtr->height);
+
+ /* Draw the text into the bitmap. Foreground is 1. */
+ XSetFont(Tk_Display(tkwin), gc, Blt_FontId(stylePtr->font));
+ XSetForeground(Tk_Display(tkwin), gc, 1);
+ Blt_DrawLayout(tkwin, bitmap, gc, stylePtr->font, 1, 0.0f, 0, 0, layoutPtr,
+ stylePtr->maxLength);
+ *bmWidthPtr = layoutPtr->width, *bmHeightPtr = layoutPtr->height;
+ return bitmap;
+}
+
+static void
+DrawStandardLayout(Tk_Window tkwin, Drawable drawable, TextStyle *stylePtr,
+ TextLayout *layoutPtr, int x, int y)
+{
+ int w, h;
+ /*
+ * This is the easy case of no rotation. Simply draw the text
+ * using the standard drawing routines. Handle offset printing
+ * for engraved (disabled) text.
+ */
+ w = layoutPtr->width;
+ h = layoutPtr->height;
+ if ((stylePtr->maxLength > 0) && (stylePtr->maxLength < w)) {
+ w = stylePtr->maxLength;
+ }
+ Blt_TranslateAnchor(x, y, w, h, stylePtr->anchor, &x, &y);
+ if (stylePtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
+ TkBorder *borderPtr = (TkBorder *) Blt_BackgroundBorder(stylePtr->bg);
+ XColor *color1, *color2;
+
+ color1 = borderPtr->lightColorPtr, color2 = borderPtr->darkColorPtr;
+ if (stylePtr->state & STATE_EMPHASIS) {
+ XColor *hold;
+
+ hold = color1, color1 = color2, color2 = hold;
+ }
+ if (color1 != NULL) {
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, color1->pixel);
+ }
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), 0.0f, x+1, y+1, layoutPtr,stylePtr->maxLength);
+ if (color2 != NULL) {
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, color2->pixel);
+ }
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), 0.0f, x, y, layoutPtr, stylePtr->maxLength);
+
+ /* Reset the foreground color back to its original setting, so not to
+ * invalidate the GC cache. */
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, stylePtr->color->pixel);
+
+ return; /* Done */
+ }
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), 0.0f, x, y, layoutPtr, stylePtr->maxLength);
+}
+
+
+static void
+RotateStartingTextPositions(TextLayout *lPtr, int w, int h, float angle)
+{
+ Point2d off1, off2;
+ TextFragment *fp, *fend;
+ double radians;
+ double rw, rh;
+ double sinTheta, cosTheta;
+
+ Blt_GetBoundingBox(w, h, angle, &rw, &rh, (Point2d *)NULL);
+ off1.x = (double)w * 0.5;
+ off1.y = (double)h * 0.5;
+ off2.x = rw * 0.5;
+ off2.y = rh * 0.5;
+ radians = (-angle / 180.0) * M_PI;
+
+ sinTheta = sin(radians), cosTheta = cos(radians);
+ for (fp = lPtr->fragments, fend = fp + lPtr->nFrags; fp < fend; fp++) {
+ Point2d p, q;
+
+ p.x = fp->x - off1.x;
+ p.y = fp->y - off1.y;
+ q.x = (p.x * cosTheta) - (p.y * sinTheta);
+ q.y = (p.x * sinTheta) + (p.y * cosTheta);
+ q.x += off2.x;
+ q.y += off2.y;
+ fp->sx = ROUND(q.x);
+ fp->sy = ROUND(q.y);
+ }
+}
+
+void
+Blt_RotateStartingTextPositions(TextLayout *lPtr, float angle)
+{
+ RotateStartingTextPositions(lPtr, lPtr->width, lPtr->height, angle);
+}
+
+int
+Blt_DrawTextWithRotatedFont(Tk_Window tkwin, Drawable drawable, float angle,
+ TextStyle *stylePtr, TextLayout *layoutPtr,
+ int x, int y)
+{
+ double rw, rh;
+ int w, h;
+
+ w = layoutPtr->width;
+ h = layoutPtr->height;
+ if ((stylePtr->maxLength > 0) && (stylePtr->maxLength < w)) {
+ w = stylePtr->maxLength;
+ }
+ RotateStartingTextPositions(layoutPtr, w, h, angle);
+ Blt_GetBoundingBox(w, h, angle, &rw, &rh, (Point2d *)NULL);
+ Blt_TranslateAnchor(x, y, (int)rw, (int)rh, stylePtr->anchor, &x, &y);
+ if (stylePtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
+ TkBorder *borderPtr = (TkBorder *)Blt_BackgroundBorder(stylePtr->bg);
+ XColor *color1, *color2;
+
+ color1 = borderPtr->lightColorPtr, color2 = borderPtr->darkColorPtr;
+ if (stylePtr->state & STATE_EMPHASIS) {
+ XColor *hold;
+
+ hold = color1, color1 = color2, color2 = hold;
+ }
+ if (color1 != NULL) {
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, color1->pixel);
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), angle, x, y, layoutPtr, stylePtr->maxLength);
+ }
+ if (color2 != NULL) {
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, color2->pixel);
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), angle, x, y, layoutPtr, stylePtr->maxLength);
+ }
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, stylePtr->color->pixel);
+ return TRUE;
+ }
+ XSetForeground(Tk_Display(tkwin), stylePtr->gc, stylePtr->color->pixel);
+ Blt_DrawLayout(tkwin, drawable, stylePtr->gc, stylePtr->font,
+ Tk_Depth(tkwin), angle, x, y, layoutPtr, stylePtr->maxLength);
+ return TRUE;
+}
+
+static void
+Blt_DrawTextWithRotatedBitmap(
+ Tk_Window tkwin,
+ Drawable drawable,
+ float angle,
+ TextStyle *stylePtr, /* Text attribute information */
+ TextLayout *layoutPtr,
+ int x, int y) /* Window coordinates to draw text */
+{
+ int width, height;
+ Display *display;
+ Pixmap bitmap;
+
+ display = Tk_Display(tkwin);
+ /*
+ * Rotate the text by writing the text into a bitmap and rotating the
+ * bitmap. Set the clip mask and origin in the GC first. And make sure
+ * we restore the GC because it may be shared.
+ */
+ stylePtr->angle = angle;
+
+ bitmap = Blt_Ts_Bitmap(tkwin, layoutPtr, stylePtr, &width, &height);
+ if (bitmap == None) {
+ return;
+ }
+ if ((bitmap != None) && (stylePtr->angle != 0.0)) {
+ Pixmap rotated;
+
+ rotated = Blt_RotateBitmap(tkwin, bitmap, width, height,
+ stylePtr->angle, &width, &height);
+ Tk_FreePixmap(display, bitmap);
+ bitmap = rotated;
+ }
+ Blt_TranslateAnchor(x, y, width, height, stylePtr->anchor, &x, &y);
+ XSetClipMask(display, stylePtr->gc, bitmap);
+
+ if (stylePtr->state & (STATE_DISABLED | STATE_EMPHASIS)) {
+ TkBorder *borderPtr = (TkBorder *) Blt_BackgroundBorder(stylePtr->bg);
+ XColor *color1, *color2;
+
+ color1 = borderPtr->lightColorPtr, color2 = borderPtr->darkColorPtr;
+ if (stylePtr->state & STATE_EMPHASIS) {
+ XColor *hold;
+
+ hold = color1, color1 = color2, color2 = hold;
+ }
+ if (color1 != NULL) {
+ XSetForeground(display, stylePtr->gc, color1->pixel);
+ }
+ XSetClipOrigin(display, stylePtr->gc, x + 1, y + 1);
+ XCopyPlane(display, bitmap, drawable, stylePtr->gc, 0, 0, width,
+ height, x + 1, y + 1, 1);
+ if (color2 != NULL) {
+ XSetForeground(display, stylePtr->gc, color2->pixel);
+ }
+ XSetClipOrigin(display, stylePtr->gc, x, y);
+ XCopyPlane(display, bitmap, drawable, stylePtr->gc, 0, 0, width,
+ height, x, y, 1);
+ XSetForeground(display, stylePtr->gc, stylePtr->color->pixel);
+ } else {
+ XSetForeground(display, stylePtr->gc, stylePtr->color->pixel);
+ XSetClipOrigin(display, stylePtr->gc, x, y);
+ XCopyPlane(display, bitmap, drawable, stylePtr->gc, 0, 0, width, height,
+ x, y, 1);
+ }
+ XSetClipMask(display, stylePtr->gc, None);
+ Tk_FreePixmap(display, bitmap);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ts_DrawLayout --
+ *
+ * Draw a text string, possibly rotated, using the the given window
+ * coordinates as an anchor for the text bounding box. If the text is
+ * not rotated, simply use the X text drawing routines. Otherwise,
+ * generate a bitmap of the rotated text.
+ *
+ * Results:
+ * Returns the x-coordinate to the right of the text.
+ *
+ * Side Effects:
+ * Text string is drawn using the given font and GC at the the given
+ * window coordinates.
+ *
+ * The Stipple, FillStyle, and TSOrigin fields of the GC are modified for
+ * rotated text. This assumes the GC is private, *not* shared (via
+ * Tk_GetGC)
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ts_DrawLayout(
+ Tk_Window tkwin,
+ Drawable drawable,
+ TextLayout *layoutPtr,
+ TextStyle *stylePtr, /* Text attribute information */
+ int x, int y) /* Window coordinates to draw text */
+{
+ float angle;
+
+ if ((stylePtr->gc == NULL) || (stylePtr->flags & UPDATE_GC)) {
+ Blt_Ts_ResetStyle(tkwin, stylePtr);
+ }
+ angle = (float)fmod(stylePtr->angle, 360.0);
+ if (angle < 0.0) {
+ angle += 360.0;
+ }
+ if (angle == 0.0) {
+ /*
+ * This is the easy case of no rotation. Simply draw the text using
+ * the standard drawing routines. Handle offset printing for engraved
+ * (disabled) text.
+ */
+ DrawStandardLayout(tkwin, drawable, stylePtr, layoutPtr, x, y);
+ return;
+ }
+ if (Blt_CanRotateFont(stylePtr->font, angle)) {
+ if (Blt_DrawTextWithRotatedFont(tkwin, drawable, angle, stylePtr,
+ layoutPtr, x, y)) {
+ return; /* Success. */
+ }
+ }
+ /*Fallthru*/
+ stylePtr->angle = (float)angle;
+ Blt_DrawTextWithRotatedBitmap(tkwin, drawable, angle, stylePtr, layoutPtr,
+ x, y);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Ts_DrawLayout --
+ *
+ * Draw a text string, possibly rotated, using the the given window
+ * coordinates as an anchor for the text bounding box. If the text is
+ * not rotated, simply use the X text drawing routines. Otherwise,
+ * generate a bitmap of the rotated text.
+ *
+ * Results:
+ * Returns the x-coordinate to the right of the text.
+ *
+ * Side Effects:
+ * Text string is drawn using the given font and GC at the the given
+ * window coordinates.
+ *
+ * The Stipple, FillStyle, and TSOrigin fields of the GC are modified for
+ * rotated text. This assumes the GC is private, *not* shared (via
+ * Tk_GetGC)
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Ts_DrawText(
+ Tk_Window tkwin,
+ Drawable drawable,
+ const char *text,
+ int textLen,
+ TextStyle *stylePtr, /* Text attribute information */
+ int x, int y) /* Window coordinates to draw text */
+{
+ TextLayout *layoutPtr;
+
+ layoutPtr = Blt_Ts_CreateLayout(text, textLen, stylePtr);
+ Blt_Ts_DrawLayout(tkwin, drawable, layoutPtr, stylePtr, x, y);
+ free(layoutPtr);
+}
+
+void
+Blt_DrawText2(
+ Tk_Window tkwin,
+ Drawable drawable,
+ const char *string,
+ TextStyle *stylePtr, /* Text attribute information */
+ int x, int y, /* Window coordinates to draw text */
+ Dim2D *areaPtr)
+{
+ TextLayout *layoutPtr;
+ int width, height;
+ float angle;
+
+ if ((string == NULL) || (*string == '\0')) {
+ return; /* Empty string, do nothing */
+ }
+ layoutPtr = Blt_Ts_CreateLayout(string, -1, stylePtr);
+ Blt_Ts_DrawLayout(tkwin, drawable, layoutPtr, stylePtr, x, y);
+ angle = fmod(stylePtr->angle, 360.0);
+ if (angle < 0.0) {
+ angle += 360.0;
+ }
+ width = layoutPtr->width;
+ height = layoutPtr->height;
+ if (angle != 0.0) {
+ double rotWidth, rotHeight;
+
+ Blt_GetBoundingBox(width, height, angle, &rotWidth, &rotHeight,
+ (Point2d *)NULL);
+ width = ROUND(rotWidth);
+ height = ROUND(rotHeight);
+ }
+ areaPtr->width = width;
+ areaPtr->height = height;
+ free(layoutPtr);
+}
+
+void
+Blt_DrawText(
+ Tk_Window tkwin,
+ Drawable drawable,
+ const char *string,
+ TextStyle *stylePtr, /* Text attribute information */
+ int x, int y) /* Window coordinates to draw text */
+{
+ TextLayout *layoutPtr;
+
+ if ((string == NULL) || (*string == '\0')) {
+ return; /* Empty string, do nothing */
+ }
+ layoutPtr = Blt_Ts_CreateLayout(string, -1, stylePtr);
+ Blt_Ts_DrawLayout(tkwin, drawable, layoutPtr, stylePtr, x, y);
+ free(layoutPtr);
+}
+
+void
+Blt_Ts_ResetStyle(Tk_Window tkwin, TextStyle *stylePtr)
+{
+ GC newGC;
+ XGCValues gcValues;
+ unsigned long gcMask;
+
+ gcMask = GCFont;
+ gcValues.font = Blt_FontId(stylePtr->font);
+ if (stylePtr->color != NULL) {
+ gcMask |= GCForeground;
+ gcValues.foreground = stylePtr->color->pixel;
+ }
+ newGC = Tk_GetGC(tkwin, gcMask, &gcValues);
+ if (stylePtr->gc != NULL) {
+ Tk_FreeGC(Tk_Display(tkwin), stylePtr->gc);
+ }
+ stylePtr->gc = newGC;
+ stylePtr->flags &= ~UPDATE_GC;
+}
+
+void
+Blt_Ts_FreeStyle(Display *display, TextStyle *stylePtr)
+{
+ if (stylePtr->gc != NULL) {
+ Tk_FreeGC(display, stylePtr->gc);
+ }
+}
+
+/*
+ * The following two structures are used to keep track of string
+ * measurement information when using the text layout facilities.
+ *
+ * A LayoutChunk represents a contiguous range of text that can be measured
+ * and displayed by low-level text calls. In general, chunks will be
+ * delimited by newlines and tabs. Low-level, platform-specific things
+ * like kerning and non-integer character widths may occur between the
+ * characters in a single chunk, but not between characters in different
+ * chunks.
+ *
+ * A TextLayout is a collection of LayoutChunks. It can be displayed with
+ * respect to any origin. It is the implementation of the Tk_TextLayout
+ * opaque token.
+ */
+
+typedef struct LayoutChunk {
+ const char *start; /* Pointer to simple string to be displayed.
+ * This is a pointer into the TkTextLayout's
+ * string. */
+ int numBytes; /* The number of bytes in this chunk. */
+ int numChars; /* The number of characters in this chunk. */
+ int numDisplayChars; /* The number of characters to display when
+ * this chunk is displayed. Can be less than
+ * numChars if extra space characters were
+ * absorbed by the end of the chunk. This
+ * will be < 0 if this is a chunk that is
+ * holding a tab or newline. */
+ int x, y; /* The origin of the first character in this
+ * chunk with respect to the upper-left hand
+ * corner of the TextLayout. */
+ int totalWidth; /* Width in pixels of this chunk. Used
+ * when hit testing the invisible spaces at
+ * the end of a chunk. */
+ int displayWidth; /* Width in pixels of the displayable
+ * characters in this chunk. Can be less than
+ * width if extra space characters were
+ * absorbed by the end of the chunk. */
+} LayoutChunk;
+
+typedef struct TkTextLayout {
+ Blt_Font font; /* The font used when laying out the text. */
+ const char *string; /* The string that was layed out. */
+ int width; /* The maximum width of all lines in the
+ * text layout. */
+ int numChunks; /* Number of chunks actually used in
+ * following array. */
+ LayoutChunk chunks[1]; /* Array of chunks. The actual size will
+ * be maxChunks. THIS FIELD MUST BE THE LAST
+ * IN THE STRUCTURE. */
+} TkTextLayout;
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeTextLayout --
+ *
+ * This procedure is called to release the storage associated with
+ * a Tk_TextLayout when it is no longer needed.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Memory is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+void
+Blt_FreeTextLayout(Tk_TextLayout textLayout)
+{
+ TkTextLayout *layoutPtr = (TkTextLayout *) textLayout;
+
+ if (layoutPtr != NULL) {
+ free(layoutPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_CharBbox --
+ *
+ * Use the information in the Tk_TextLayout token to return the
+ * bounding box for the character specified by index.
+ *
+ * The width of the bounding box is the advance width of the
+ * character, and does not include and left- or right-bearing.
+ * Any character that extends partially outside of the
+ * text layout is considered to be truncated at the edge. Any
+ * character which is located completely outside of the text
+ * layout is considered to be zero-width and pegged against
+ * the edge.
+ *
+ * The height of the bounding box is the line height for this font,
+ * extending from the top of the ascent to the bottom of the
+ * descent. Information about the actual height of the individual
+ * letter is not available.
+ *
+ * A text layout that contains no characters is considered to
+ * contain a single zero-width placeholder character.
+ *
+ * Results:
+ * The return value is 0 if the index did not specify a character
+ * in the text layout, or non-zero otherwise. In that case,
+ * *bbox is filled with the bounding box of the character.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Blt_CharBbox(
+ Tk_TextLayout layout, /* Layout information, from a previous call to
+ * Tk_ComputeTextLayout(). */
+ int index, /* The index of the character whose bbox is
+ * desired. */
+ int *xPtr, int *yPtr, /* Filled with the upper-left hand corner, in
+ * pixels, of the bounding box for the character
+ * specified by index, if non-NULL. */
+ int *widthPtr,
+ int *heightPtr) /* Filled with the width and height of the
+ * bounding box for the character specified by
+ * index, if non-NULL. */
+{
+ TkTextLayout *layoutPtr;
+ LayoutChunk *chunkPtr;
+ int i, x, w;
+ Blt_Font font;
+ const char *end;
+ Blt_FontMetrics fm;
+
+ if (index < 0) {
+ return 0;
+ }
+
+ layoutPtr = (TkTextLayout *) layout;
+ chunkPtr = layoutPtr->chunks;
+ font = layoutPtr->font;
+
+ Blt_GetFontMetrics(font, &fm);
+ for (i = 0; i < layoutPtr->numChunks; i++) {
+ if (chunkPtr->numDisplayChars < 0) {
+ if (index == 0) {
+ x = chunkPtr->x;
+ w = chunkPtr->totalWidth;
+ goto check;
+ }
+ } else if (index < chunkPtr->numChars) {
+ end = Tcl_UtfAtIndex(chunkPtr->start, index);
+ if (xPtr != NULL) {
+ Blt_MeasureChars(font, chunkPtr->start,
+ end - chunkPtr->start, -1, 0, &x);
+ x += chunkPtr->x;
+ }
+ if (widthPtr != NULL) {
+ Blt_MeasureChars(font, end, Tcl_UtfNext(end) - end, -1, 0, &w);
+ }
+ goto check;
+ }
+ index -= chunkPtr->numChars;
+ chunkPtr++;
+ }
+ if (index == 0) {
+ /*
+ * Special case to get location just past last char in layout.
+ */
+
+ chunkPtr--;
+ x = chunkPtr->x + chunkPtr->totalWidth;
+ w = 0;
+ } else {
+ return 0;
+ }
+
+ /*
+ * Ensure that the bbox lies within the text layout. This forces all
+ * chars that extend off the right edge of the text layout to have
+ * truncated widths, and all chars that are completely off the right
+ * edge of the text layout to peg to the edge and have 0 width.
+ */
+ check:
+ if (yPtr != NULL) {
+ *yPtr = chunkPtr->y - fm.ascent;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = fm.ascent + fm.descent;
+ }
+
+ if (x > layoutPtr->width) {
+ x = layoutPtr->width;
+ }
+ if (xPtr != NULL) {
+ *xPtr = x;
+ }
+ if (widthPtr != NULL) {
+ if (x + w > layoutPtr->width) {
+ w = layoutPtr->width - x;
+ }
+ *widthPtr = w;
+ }
+
+ return 1;
+}
+
diff --git a/tlt3.0/bltText.h b/tlt3.0/bltText.h
new file mode 100644
index 0000000..f59953b
--- /dev/null
+++ b/tlt3.0/bltText.h
@@ -0,0 +1,240 @@
+/*
+ * bltText.h --
+ *
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_TEXT_H
+#define _BLT_TEXT_H
+
+#include "bltBgStyle.h"
+
+#define DEF_TEXT_FLAGS (TK_PARTIAL_OK | TK_IGNORE_NEWLINES)
+#define UPDATE_GC 1
+
+/*
+ * TextFragment --
+ */
+typedef struct {
+ const char *text; /* Text string to be displayed */
+
+ size_t count; /* Number of bytes in text. The actual
+ * character count may differ because of
+ * multi-byte UTF encodings. */
+
+ short x, y; /* X-Y offset of the baseline from the
+ * upper-left corner of the bbox. */
+
+ short sx, sy; /* Starting offset of text using rotated
+ * font. */
+
+ int width; /* Width of segment in pixels. This
+ * information is used to draw
+ * PostScript strings the same width
+ * as X. */
+} TextFragment;
+
+
+/*
+ * TextItem --
+ *
+ * Parsed form for markup string. Each item is a scrap of text
+ * describes the font, position, and characters to be displayed.
+ *
+ * subscript x_y very small subset of latex markup.
+ * superscript x^y
+ * grouping a^{x+y} a_{i,j}
+ * supersuper a^{10^8}
+ * \hat{a} \bar{b} \vec{c}
+ * \overline{} \underline{}
+ * \frac \tfrac
+ * \Alpha \Beta ...
+ * \mathbf{} \mathit{} \mathrm{} \boldsymbol{}
+ * \angstrom \degree
+ *
+ * -mathtext instead of -text
+ *
+ * Can use TextItem where you don't directly edit the text:
+ * label, treeview, graph, barchart...
+ *
+ * Font selector (bold, italic, size adjust) from base font.
+ * Global font table reference counted.
+ *
+ */
+typedef struct {
+ const char *text; /* Text string to be displayed */
+
+ size_t count; /* Number of bytes in text. The actual
+ * character count may differ because of
+ * multi-byte UTF encodings. */
+
+ short int x, y; /* X-Y offset of the baseline from the
+ * upper-left corner of the bbox. */
+
+ short int sx, sy; /* Starting offset of text using rotated
+ * font. */
+
+ Blt_Font font; /* Allocated font for this chunk.
+ * If NULL, use the global font. */
+
+ int underline; /* Text is underlined */
+
+ int width; /* Width of segment in pixels. This
+ * information is used to draw
+ * PostScript strings the same width
+ * as X. (deprecated) */
+} TextItem;
+
+/*
+ * TextLayout --
+ */
+typedef struct {
+ TextFragment *underlinePtr;
+ int underline;
+ size_t width, height; /* Dimensions of text bounding box */
+ size_t nFrags; /* # fragments of text */
+ TextFragment fragments[1]; /* Information about each fragment of text */
+} TextLayout;
+
+/*
+ * TextStyle --
+ *
+ * A somewhat convenient structure to hold text attributes that determine
+ * how a text string is to be displayed on the screen or drawn with
+ * PostScript commands. The alternative is to pass lots of parameters to
+ * the drawing and printing routines. This seems like a more efficient
+ * and less cumbersome way of passing parameters.
+ */
+typedef struct {
+ unsigned int state; /* If non-zero, indicates to draw text
+ * in the active color */
+ XColor *color; /* Color to draw the text. */
+ Blt_Font font; /* Font to use to draw text */
+ Blt_Background bg; /* Background color of text. This is
+ * also used for drawing disabled
+ * text. */
+ float angle; /* Rotation of text in degrees. */
+ Tk_Justify justify; /* Justification of the text
+ * string. This only matters if the
+ * text is composed of multiple
+ * lines. */
+ Tk_Anchor anchor; /* Indicates how the text is anchored
+ * around its x,y coordinates. */
+ Blt_Pad xPad, yPad; /* # pixels padding of around text
+ * region. */
+ unsigned short int leader; /* # pixels spacing between lines of
+ * text. */
+ short int underline; /* Index of character to be underlined,
+ * -1 if no underline. */
+ int maxLength; /* Maximum length in pixels of text */
+ /* Private fields. */
+ unsigned short flags;
+ GC gc; /* GC used to draw the text */
+} TextStyle;
+
+extern TextLayout *Blt_Ts_CreateLayout(const char *string, int length,
+ TextStyle *tsPtr);
+
+extern void Blt_Ts_DrawLayout(Tk_Window tkwin, Drawable drawable,
+ TextLayout *textPtr, TextStyle *tsPtr, int x, int y);
+
+extern void Blt_Ts_GetExtents(TextStyle *tsPtr, const char *text,
+ unsigned int *widthPtr, unsigned int *heightPtr);
+
+extern void Blt_Ts_ResetStyle(Tk_Window tkwin, TextStyle *tsPtr);
+
+extern void Blt_Ts_FreeStyle(Display *display, TextStyle *tsPtr);
+
+extern void Blt_DrawText(Tk_Window tkwin, Drawable drawable,
+ const char *string, TextStyle *tsPtr, int x, int y);
+
+extern void Blt_DrawText2(Tk_Window tkwin, Drawable drawable,
+ const char *string, TextStyle *tsPtr, int x, int y, Dim2D * dimPtr);
+
+extern Pixmap Blt_Ts_Bitmap(Tk_Window tkwin, TextLayout *textPtr,
+ TextStyle *tsPtr, int *widthPtr, int *heightPtr);
+
+extern int Blt_DrawTextWithRotatedFont(Tk_Window tkwin, Drawable drawable,
+ float angle, TextStyle *tsPtr, TextLayout *textPtr, int x, int y);
+
+extern void Blt_DrawLayout(Tk_Window tkwin, Drawable drawable, GC gc,
+ Blt_Font font, int depth, float angle, int x, int y,
+ TextLayout *layoutPtr, int maxLength);
+
+extern void Blt_GetTextExtents(Blt_Font font, int leader, const char *text,
+ int textLen, unsigned int *widthPtr, unsigned int *heightPtr);
+
+extern void Blt_RotateStartingTextPositions(TextLayout *textPtr,
+ float angle);
+
+extern int Blt_CharBbox(Tk_TextLayout layout, int index, int *xPtr,
+ int *yPtr, int *widthPtr, int *heightPtr);
+
+extern void Blt_Ts_DrawText(Tk_Window tkwin, Drawable drawable,
+ const char *text, int textLen, TextStyle *tsPtr, int x, int y);
+
+extern void Blt_FreeTextLayout(Tk_TextLayout layout);
+
+#define Blt_Ts_GetAnchor(ts) ((ts).anchor)
+#define Blt_Ts_GetAngle(ts) ((ts).angle)
+#define Blt_Ts_GetBackground(ts) ((ts).bg)
+#define Blt_Ts_GetFont(ts) ((ts).font)
+#define Blt_Ts_GetForeground(ts) ((ts).color)
+#define Blt_Ts_GetJustify(ts) ((ts).justify)
+#define Blt_Ts_GetLeader(ts) ((ts).leader)
+
+#define Blt_Ts_SetAnchor(ts, a) ((ts).anchor = (a))
+#define Blt_Ts_SetAngle(ts, r) ((ts).angle = (float)(r))
+#define Blt_Ts_SetBackground(ts, b) ((ts).bg = (b))
+#define Blt_Ts_SetFont(ts, f) \
+ (((ts).font != (f)) ? ((ts).font = (f), (ts).flags |= UPDATE_GC) : 0)
+#define Blt_Ts_SetForeground(ts, c) \
+ (((ts).color != (c)) ? ((ts).color = (c), (ts).flags |= UPDATE_GC) : 0)
+#define Blt_Ts_SetGC(ts, g) ((ts).gc = (g))
+#define Blt_Ts_SetJustify(ts, j) ((ts).justify = (j))
+#define Blt_Ts_SetLeader(ts, l) ((ts).leader = (l))
+#define Blt_Ts_SetMaxLength(ts, l) ((ts).maxLength = (l))
+#define Blt_Ts_SetPadding(ts, l, r, t, b) \
+ ((ts).xPad.side1 = (l), \
+ (ts).xPad.side2 = (r), \
+ (ts).yPad.side1 = (t), \
+ (ts).yPad.side2 = (b))
+#define Blt_Ts_SetState(ts, s) ((ts).state = (s))
+#define Blt_Ts_SetUnderline(ts, ul) ((ts).underline = (ul))
+
+#define Blt_Ts_InitStyle(ts) \
+ ((ts).anchor = TK_ANCHOR_NW, \
+ (ts).color = (XColor *)NULL, \
+ (ts).font = NULL, \
+ (ts).justify = TK_JUSTIFY_LEFT, \
+ (ts).leader = 0, \
+ (ts).underline = -1, \
+ (ts).xPad.side1 = (ts).xPad.side2 = 0, \
+ (ts).yPad.side1 = (ts).yPad.side2 = 0, \
+ (ts).state = 0, \
+ (ts).flags = 0, \
+ (ts).gc = NULL, \
+ (ts).maxLength = -1, \
+ (ts).angle = 0.0)
+
+#endif /* _BLT_TEXT_H */
diff --git a/tlt3.0/bltUnixFont.c b/tlt3.0/bltUnixFont.c
new file mode 100644
index 0000000..cdc1661
--- /dev/null
+++ b/tlt3.0/bltUnixFont.c
@@ -0,0 +1,2658 @@
+/*
+ * bltUnixFont.c --
+ *
+ * This module implements freetype (Xft) and Tk fonts for the BLT toolkit.
+ *
+ * The Blt_Font is a wrapper around the existing Tk font structure, adding
+ * Freetype fonts (via the XRender extension). The original Tk font
+ * procedures act as a fallback if a suitable Xft enabled server can't be
+ * found.
+ *
+ * Copyright 2005 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <ctype.h>
+
+#ifdef HAVE_LIBXFT
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <X11/Xft/Xft.h>
+#endif
+
+#include <tkPort.h>
+#include <tkInt.h>
+#include <tkFont.h>
+
+#include "bltInt.h"
+#include "bltHash.h"
+#include "bltFont.h"
+#include "bltPs.h"
+
+/*
+ * This module provides antialiased fonts via Freetype as now does Tk 8.5.
+ * This version also includes rotated fonts. No subfont matching is done to
+ * avoid rotating dozens of subfonts for every rotated font. It's possible
+ * that glyphs may be missing that exist in the Tk version. The trade-off
+ * seems fair when weighing the benefit of high-quality antialiased rotated
+ * fonts.
+ *
+ * Font rotation is done via the freetype font matrix for outline fonts. For
+ * bitmap fonts we fall back on drawing the text into a bitmap and rotate the
+ * bitmap. This requires depth-aware versions of Tk_DrawChars, since Xft is
+ * drawing into a drawable of a different depth (depth is 1).
+ *
+ * The best tactic is to 1) not use bitmapped fonts if better outline fonts
+ * are available and 2) provide our own font handling routines that allow font
+ * rotation and font aliasing. The font aliases allow us to use a font name
+ * like "Sans Serif" that translates into a good font for that platform and
+ * set of fonts available (Xft or Xlfd font).
+ */
+
+typedef struct _Blt_Font _Blt_Font;
+
+enum FontTypes {
+ FONT_UNKNOWN, /* Unknown font type. */
+ FONT_TK, /* Normal Tk font. */
+ FONT_FT /* Freetype font. */
+};
+
+#ifndef HAVE_LIBXFT
+#define FC_WEIGHT_THIN 0
+#define FC_WEIGHT_EXTRALIGHT 40
+#define FC_WEIGHT_ULTRALIGHT FC_WEIGHT_EXTRALIGHT
+#define FC_WEIGHT_LIGHT 50
+#define FC_WEIGHT_BOOK 75
+#define FC_WEIGHT_REGULAR 80
+#define FC_WEIGHT_NORMAL FC_WEIGHT_REGULAR
+#define FC_WEIGHT_MEDIUM 100
+#define FC_WEIGHT_DEMIBOLD 180
+#define FC_WEIGHT_SEMIBOLD FC_WEIGHT_DEMIBOLD
+#define FC_WEIGHT_BOLD 200
+#define FC_WEIGHT_EXTRABOLD 205
+#define FC_WEIGHT_ULTRABOLD FC_WEIGHT_EXTRABOLD
+#define FC_WEIGHT_BLACK 210
+#define FC_WEIGHT_HEAVY FC_WEIGHT_BLACK
+#define FC_WEIGHT_EXTRABLACK 215
+#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_EXTRABLACK
+
+#define FC_SLANT_ROMAN 0
+#define FC_SLANT_ITALIC 100
+#define FC_SLANT_OBLIQUE 110
+
+#define FC_WIDTH_ULTRACONDENSED 50
+#define FC_WIDTH_EXTRACONDENSED 63
+#define FC_WIDTH_CONDENSED 75
+#define FC_WIDTH_SEMICONDENSED 87
+#define FC_WIDTH_NORMAL 100
+#define FC_WIDTH_SEMIEXPANDED 113
+#define FC_WIDTH_EXPANDED 125
+#define FC_WIDTH_EXTRAEXPANDED 150
+#define FC_WIDTH_ULTRAEXPANDED 200
+
+#define FC_PROPORTIONAL 0
+#define FC_DUAL 90
+#define FC_MONO 100
+#define FC_CHARCELL 110
+
+#define FC_ANTIALIAS "antialias" /* Bool (depends) */
+#define FC_AUTOHINT "autohint" /* Bool (false) */
+#define FC_DECORATIVE "decorative" /* Bool */
+#define FC_EMBEDDED_BITMAP "embeddedbitmap" /* Bool */
+#define FC_EMBOLDEN "embolden" /* Bool */
+#define FC_FAMILY "family" /* String */
+#define FC_GLOBAL_ADVANCE "globaladvance" /* Bool (true) */
+#define FC_HINTING "hinting" /* Bool (true) */
+#define FC_MINSPACE "minspace" /* Bool */
+#define FC_OUTLINE "outline" /* Bool */
+#define FC_SCALABLE "scalable" /* Bool */
+#define FC_SIZE "size" /* Double */
+#define FC_SLANT "slant" /* Int */
+#define FC_SPACING "spacing" /* Int */
+#define FC_STYLE "style" /* String */
+#define FC_VERTICAL_LAYOUT "verticallayout" /* Bool (false) */
+#define FC_WEIGHT "weight" /* Int */
+#define FC_WIDTH "width" /* Int */
+
+#endif
+
+#ifndef FC_WEIGHT_EXTRABLACK
+#define FC_WEIGHT_EXTRABLACK 215
+#define FC_WEIGHT_ULTRABLACK FC_WEIGHT_EXTRABLACK
+#endif
+
+typedef struct {
+ char *family;
+ const char *weight;
+ const char *slant;
+ const char *width;
+ const char *spacing;
+ int size; /* If negative, pixels, else points */
+} TkFontPattern;
+
+typedef struct {
+ const char *name;
+ int minChars;
+ const char *key;
+ int value;
+ const char *oldvalue;
+} FontSpec;
+
+static FontSpec fontSpecs[] = {
+ { "black", 2, FC_WEIGHT, FC_WEIGHT_BLACK, "*"},
+ { "bold", 3, FC_WEIGHT, FC_WEIGHT_BOLD, "bold"},
+ { "book", 3, FC_WEIGHT, FC_WEIGHT_MEDIUM, "medium"},
+ { "charcell", 2, FC_SPACING, FC_CHARCELL, "c"},
+ { "condensed", 2, FC_WIDTH, FC_WIDTH_CONDENSED, "condensed"},
+ { "demi", 4, FC_WEIGHT, FC_WEIGHT_BOLD, "semi"},
+ { "demibold", 5, FC_WEIGHT, FC_WEIGHT_DEMIBOLD, "semibold"},
+ { "dual", 2, FC_SPACING, FC_DUAL, "*"},
+ { "i", 1, FC_SLANT, FC_SLANT_ITALIC, "i"},
+ { "italic", 2, FC_SLANT, FC_SLANT_ITALIC, "i"},
+ { "light", 1, FC_WEIGHT, FC_WEIGHT_LIGHT, "light"},
+ { "medium", 2, FC_WEIGHT, FC_WEIGHT_MEDIUM, "medium"},
+ { "mono", 2, FC_SPACING, FC_MONO, "m"},
+ { "normal", 1, FC_WIDTH, FC_WIDTH_NORMAL, "normal"},
+ { "o", 1, FC_SLANT, FC_SLANT_OBLIQUE, "o"},
+ { "obilque", 2, FC_SLANT, FC_SLANT_OBLIQUE, "o"},
+ { "overstrike", 2, NULL, 0, "*"},
+ { "proportional", 1, FC_SPACING, FC_PROPORTIONAL, "p"},
+ { "r", 1, FC_SLANT, FC_SLANT_ROMAN, "r"},
+ { "roman", 2, FC_SLANT, FC_SLANT_ROMAN, "r"},
+ { "semibold", 5, FC_WEIGHT, FC_WEIGHT_DEMIBOLD, "semibold"},
+ { "semicondensed",5, FC_WIDTH, FC_WIDTH_SEMICONDENSED, "semicondensed"},
+ { "underline", 1, NULL, 0, "*"},
+};
+static int nFontSpecs = sizeof(fontSpecs) / sizeof(FontSpec);
+
+static FontSpec weightSpecs[] ={
+ { "black", 2, FC_WEIGHT, FC_WEIGHT_BLACK, "bold"},
+ { "bold", 3, FC_WEIGHT, FC_WEIGHT_BOLD, "bold"},
+ { "book", 3, FC_WEIGHT, FC_WEIGHT_MEDIUM, "*"},
+ { "demi", 4, FC_WEIGHT, FC_WEIGHT_BOLD, "*"},
+ { "demibold", 5, FC_WEIGHT, FC_WEIGHT_DEMIBOLD, "*"},
+ { "extrablack", 6, FC_WEIGHT, FC_WEIGHT_EXTRABLACK, "*"},
+ { "extralight", 6, FC_WEIGHT, FC_WEIGHT_EXTRALIGHT, "*"},
+ { "heavy", 1, FC_WEIGHT, FC_WEIGHT_HEAVY, "*"},
+ { "light", 1, FC_WEIGHT, FC_WEIGHT_LIGHT, "light"},
+ { "medium", 1, FC_WEIGHT, FC_WEIGHT_MEDIUM, "medium"},
+ { "normal", 1, FC_WEIGHT, FC_WEIGHT_MEDIUM, "normal"},
+ { "regular", 1, FC_WEIGHT, FC_WEIGHT_REGULAR, "medium"},
+ { "semibold", 1, FC_WEIGHT, FC_WEIGHT_SEMIBOLD, "semibold"},
+ { "thin", 1, FC_WEIGHT, FC_WEIGHT_THIN, "thin"},
+ { "ultrablack", 7, FC_WEIGHT, FC_WEIGHT_ULTRABLACK, "*"},
+ { "ultrabold", 7, FC_WEIGHT, FC_WEIGHT_ULTRABOLD, "*"},
+ { "ultralight", 6, FC_WEIGHT, FC_WEIGHT_ULTRALIGHT, "*"},
+};
+static int nWeightSpecs = sizeof(weightSpecs) / sizeof(FontSpec);
+
+static FontSpec slantSpecs[] ={
+ { "i", 1, FC_SLANT, FC_SLANT_ITALIC, "i"},
+ { "italic", 2, FC_SLANT, FC_SLANT_ITALIC, "i"},
+ { "o", 1, FC_SLANT, FC_SLANT_OBLIQUE, "o"},
+ { "obilque", 3, FC_SLANT, FC_SLANT_OBLIQUE, "o"},
+ { "r", 1, FC_SLANT, FC_SLANT_ROMAN, "r"},
+ { "roman", 2, FC_SLANT, FC_SLANT_ROMAN, "r"},
+};
+static int nSlantSpecs = sizeof(slantSpecs) / sizeof(FontSpec);
+
+static FontSpec widthSpecs[] ={
+ { "condensed", 1, FC_WIDTH, FC_WIDTH_CONDENSED, "condensed"},
+ { "expanded", 3, FC_WIDTH, FC_WIDTH_EXPANDED, "*"},
+ { "extracondensed", 6, FC_WIDTH, FC_WIDTH_EXTRACONDENSED, "*"},
+ { "extraexpanded", 6, FC_WIDTH, FC_WIDTH_EXTRAEXPANDED, "*"},
+ { "narrow", 2, FC_WIDTH, FC_WIDTH_CONDENSED, "narrow"},
+ { "normal", 2, FC_WIDTH, FC_WIDTH_NORMAL, "normal"},
+ { "semicondensed", 5, FC_WIDTH, FC_WIDTH_SEMICONDENSED, "semicondensed"},
+ { "semiexpanded", 5, FC_WIDTH, FC_WIDTH_SEMIEXPANDED, "*"},
+ { "ultracondensed", 6, FC_WIDTH, FC_WIDTH_ULTRACONDENSED, "*"},
+ { "ultraexpanded", 6, FC_WIDTH, FC_WIDTH_ULTRAEXPANDED, "*"},
+};
+static int nWidthSpecs = sizeof(widthSpecs) / sizeof(FontSpec);
+
+static FontSpec spacingSpecs[] = {
+ { "charcell", 2, FC_SPACING, FC_CHARCELL, "c"},
+ { "dual", 2, FC_SPACING, FC_DUAL, "*"},
+ { "mono", 2, FC_SPACING, FC_MONO, "m"},
+ { "proportional", 1, FC_SPACING, FC_PROPORTIONAL, "p"},
+};
+static int nSpacingSpecs = sizeof(spacingSpecs) / sizeof(FontSpec);
+
+static Blt_HashTable fontTable;
+static void TkGetFontFamilies(Tk_Window tkwin, Blt_HashTable *tablePtr);
+
+#ifdef HAVE_LIBXFT
+static void FtGetFontFamilies(Tk_Window tkwin, Blt_HashTable *tablePtr);
+static int initialized = FALSE;
+
+static int
+IsXRenderAvailable(Tk_Window tkwin)
+{
+ static int isXRenderAvail = -1;
+
+ if (isXRenderAvail < 0) {
+ int eventBase, errorBase;
+
+ isXRenderAvail = FALSE;
+ Blt_InitHashTable(&fontTable, BLT_STRING_KEYS);
+ initialized = TRUE;
+ if (!XRenderQueryExtension(Tk_Display(tkwin), &eventBase, &errorBase)) {
+ return FALSE;
+ }
+ if (XRenderFindVisualFormat(Tk_Display(tkwin), Tk_Visual(tkwin)) == 0) {
+ return FALSE;
+ }
+ isXRenderAvail = TRUE;
+ }
+ return isXRenderAvail;
+}
+#endif
+
+static double
+PointsToPixels(Tk_Window tkwin, int size)
+{
+ double d;
+
+ if (size < 0) {
+ return -size;
+ }
+ d = size * 25.4 / 72.0;
+ d *= WidthOfScreen(Tk_Screen(tkwin));
+ d /= WidthMMOfScreen(Tk_Screen(tkwin));
+ return d;
+}
+
+static double
+PixelsToPoints(Tk_Window tkwin, int size)
+{
+ double d;
+
+ if (size >= 0) {
+ return size;
+ }
+ d = -size * 72.0 / 25.4;
+ d *= WidthMMOfScreen(Tk_Screen(tkwin));
+ d /= WidthOfScreen(Tk_Screen(tkwin));
+ return d;
+}
+
+static void
+ParseXLFD(const char *fontName, int *argcPtr, char ***argvPtr)
+{
+ char *p, *pend, *desc, *buf;
+ size_t arrayLen, stringLen;
+ int count;
+ char **field;
+
+ arrayLen = (sizeof(char *) * (XLFD_NUMFIELDS + 1));
+ stringLen = strlen(fontName);
+ buf = calloc(1, arrayLen + stringLen + 1);
+ desc = buf + arrayLen;
+ strcpy(desc, fontName);
+ field = (char **)buf;
+
+ count = 0;
+ for (p = desc, pend = p + stringLen; p < pend; p++, count++) {
+ char *word;
+
+ field[count] = NULL;
+ /* Get the next word, separated by dashes (-). */
+ word = p;
+ while ((*p != '\0') && (*p != '-')) {
+ if (((*p & 0x80) == 0) && Tcl_UniCharIsUpper((unsigned char)(*p))) {
+ *p = (char)Tcl_UniCharToLower((unsigned char)(*p));
+ }
+ p++;
+ }
+ if (*p != '\0') {
+ *p = '\0';
+ }
+ if ((word[0] == '\0') ||
+ (((word[0] == '*') || (word[0] == '?')) && (word[1] == '\0'))) {
+ continue; /* Field not specified. -- -*- -?- */
+ }
+ field[count] = word;
+ }
+
+ /*
+ * An XLFD of the form -adobe-times-medium-r-*-12-*-* is pretty common,
+ * but it is (strictly) malformed, because the first * is eliding both the
+ * Setwidth and the Addstyle fields. If the Addstyle field is a number,
+ * then assume the above incorrect form was used and shift all the rest of
+ * the fields right by one, so the number gets interpreted as a pixelsize.
+ * This fix is so that we don't get a million reports that "it works under
+ * X (as a native font name), but gives a syntax error under Windows (as a
+ * parsed set of attributes)".
+ */
+
+ if ((count > XLFD_ADD_STYLE) && (field[XLFD_ADD_STYLE] != NULL)) {
+ int dummy;
+
+ if (Tcl_GetInt(NULL, field[XLFD_ADD_STYLE], &dummy) == TCL_OK) {
+ int j;
+
+ for (j = XLFD_NUMFIELDS - 1; j >= XLFD_ADD_STYLE; j--) {
+ field[j + 1] = field[j];
+ }
+ field[XLFD_ADD_STYLE] = NULL;
+ count++;
+ }
+ }
+ *argcPtr = count;
+ *argvPtr = field;
+
+ field[XLFD_NUMFIELDS] = NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SearchForFontSpec --
+ *
+ * Performs a binary search on the array of font specification to find a
+ * partial, anchored match for the given option string.
+ *
+ * Results:
+ * If the string matches unambiguously the index of the specification in
+ * the array is returned. If the string does not match, even as an
+ * abbreviation, any operation, -1 is returned. If the string matches,
+ * but ambiguously -2 is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+SearchForFontSpec(
+ FontSpec *table, /* Table of font options. */
+ int nSpecs, /* # specifications in font spec table. */
+ const char *string) /* Name of font option to search for. */
+{
+ char c;
+ int high, low;
+ size_t length;
+
+ low = 0;
+ high = nSpecs - 1;
+ c = tolower((unsigned char)string[0]);
+ length = strlen(string);
+ while (low <= high) {
+ FontSpec *sp;
+ int compare;
+ int median;
+
+ median = (low + high) >> 1;
+ sp = table + median;
+
+ /* Test the first character */
+ compare = c - sp->name[0];
+ if (compare == 0) {
+ /* Now test the entire string */
+ compare = strncasecmp(string, sp->name, length);
+ if (compare == 0) {
+ if ((int)length < sp->minChars) {
+ return -2; /* Ambiguous spec name */
+ }
+ }
+ }
+ if (compare < 0) {
+ high = median - 1;
+ } else if (compare > 0) {
+ low = median + 1;
+ } else {
+ return median; /* Spec found. */
+ }
+ }
+ return -1; /* Can't find spec */
+}
+
+static FontSpec *
+FindSpec(Tcl_Interp *interp, FontSpec *tablePtr, int nSpecs, const char *string)
+{
+ int n;
+
+ n = SearchForFontSpec(tablePtr, nSpecs, string);
+ if (n < 0) {
+ if (n == -1) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown ", tablePtr[0].key,
+ " specification \"", string, "\"", (char *)NULL);
+ }
+ }
+ if (n == -2) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "ambiguous ", tablePtr[0].key,
+ " specification \"", string, "\"", (char *)NULL);
+ }
+ }
+ return NULL;
+ }
+ return tablePtr + n;
+}
+
+static Blt_HashTable aliasTable;
+static int alias_initialized = 0;
+
+typedef struct {
+ const char *name, *aliases[10];
+} FontAlias;
+
+#ifdef HAVE_LIBXFT
+static FontAlias xftFontAliases[] = {
+ { "math", { "mathematica1", "nimbus sans l condensed", "courier"}},
+ { "serif", { "times new roman", "nimbus roman no9 l" "times" }},
+ { "sans serif", { "arial", "nimbus sans l", "helvetica" }},
+ { "monospace", { "courier new", "nimbus mono l", "courier" }},
+ { "symbol", { "standard symbols l", "symbol" }},
+ { NULL }
+};
+#endif
+
+static FontAlias xlfdFontAliases[] = {
+ { "math", {"courier"}},
+ { "serif", {"times"}},
+ { "sans serif", { "helvetica" }},
+ { "monospace", { "courier" }},
+ { NULL }
+};
+
+static void
+MakeAliasTable(Tk_Window tkwin)
+{
+ Blt_HashTable familyTable;
+ FontAlias *fp;
+ FontAlias *table;
+
+ Blt_InitHashTable(&familyTable, TCL_STRING_KEYS);
+#ifdef HAVE_LIBXFT
+ if (IsXRenderAvailable(tkwin)) {
+ FtGetFontFamilies(tkwin, &familyTable);
+ } else {
+ TkGetFontFamilies(tkwin, &familyTable);
+ }
+#else
+ TkGetFontFamilies(tkwin, &familyTable);
+#endif
+ Blt_InitHashTable(&aliasTable, TCL_STRING_KEYS);
+#ifdef HAVE_LIBXFT
+ table = (IsXRenderAvailable(tkwin)) ? xftFontAliases : xlfdFontAliases;
+#else
+ table = xlfdFontAliases;
+#endif
+ for(fp = table; fp->name != NULL; fp++) {
+ Blt_HashEntry *hPtr;
+ const char **alias;
+
+ for (alias = fp->aliases; *alias != NULL; alias++) {
+ hPtr = Blt_FindHashEntry(&familyTable, *alias);
+ if (hPtr != NULL) {
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&aliasTable, fp->name, &isNew);
+ Blt_SetHashValue(hPtr, *alias);
+ break;
+ }
+ }
+ }
+ Blt_DeleteHashTable(&familyTable);
+}
+
+static const char *
+GetAlias(const char *family)
+{
+ Blt_HashEntry *hPtr;
+
+ strtolower((char *)family);
+ hPtr = Blt_FindHashEntry(&aliasTable, family);
+ if (hPtr != NULL) {
+ return Blt_GetHashValue(hPtr);
+ }
+ return family;
+}
+
+static Blt_NameOfFontProc TkNameOfFontProc;
+static Blt_GetFontMetricsProc TkGetFontMetricsProc;
+static Blt_FontIdProc TkFontIdProc;
+static Blt_MeasureCharsProc TkMeasureCharsProc;
+static Blt_TextStringWidthProc TkTextStringWidthProc;
+static Blt_FreeFontProc TkFreeFontProc;
+static Blt_DrawCharsProc TkDrawCharsProc;
+static Blt_PostscriptFontNameProc TkPostscriptFontNameProc;
+static Blt_FamilyOfFontProc TkFamilyOfFontProc;
+static Blt_CanRotateFontProc TkCanRotateFontProc;
+static Blt_UnderlineCharsProc TkUnderlineCharsProc;
+
+static Blt_FontClass tkFontClass = {
+ FONT_TK,
+ TkNameOfFontProc, /* Blt_NameOfFontProc */
+ TkFamilyOfFontProc, /* Blt_FamilyOfFontProc */
+ TkFontIdProc, /* Blt_FontIdProc */
+ TkGetFontMetricsProc, /* Blt_GetFontMetricsProc */
+ TkMeasureCharsProc, /* Blt_MeasureCharsProc */
+ TkTextStringWidthProc, /* Blt_TextWidthProc */
+ TkCanRotateFontProc, /* Blt_CanRotateFontProc */
+ TkDrawCharsProc, /* Blt_DrawCharsProc */
+ TkPostscriptFontNameProc, /* Blt_PostscriptFontNameProc */
+ TkFreeFontProc, /* Blt_FreeFontProc */
+ TkUnderlineCharsProc, /* Blt_UnderlineCharsProc */
+};
+
+static TkFontPattern *
+TkNewFontPattern(void)
+{
+ TkFontPattern *patternPtr;
+
+ patternPtr = calloc(1, sizeof(TkFontPattern));
+ return patternPtr;
+}
+
+static void
+TkFreeFontPattern(TkFontPattern *patternPtr)
+{
+ if (patternPtr->family != NULL) {
+ free((char *)patternPtr->family);
+ }
+ free(patternPtr);
+}
+
+
+static void
+TkGetFontFamilies(Tk_Window tkwin, Blt_HashTable *tablePtr)
+{
+ char **list, **np, **nend;
+ const char *pat;
+ int n;
+
+ pat = "-*-*-*-*-*-*-*-*-*-*-*-*-*-*";
+ list = XListFonts(Tk_Display(tkwin), pat, 10000, &n);
+ for (np = list, nend = np + n; np < nend; np++) {
+ Blt_HashEntry *hPtr;
+ int isNew;
+ char *family, *dash;
+
+ /* Parse out the family name. Assume the names are all lower case. */
+ dash = strchr(*np+1, '-');
+ if (dash == NULL) {
+ continue;
+ }
+ family = dash+1;
+ dash = strchr(family, '-');
+ if (dash != NULL) {
+ *dash = '\0';
+ }
+ hPtr = Blt_CreateHashEntry(tablePtr, family, &isNew);
+ Blt_SetHashValue(hPtr, NULL);
+ }
+ XFreeFontNames(list);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkParseTkDesc --
+ *
+ * Parses an array of Tcl_Objs as a Tk style font description .
+ *
+ * "family [size] [optionList]"
+ *
+ * Results:
+ * Returns a pattern structure, filling in with the necessary fields.
+ * Returns NULL if objv doesn't contain a Tk font description.
+ *
+ * Side effects:
+ * Memory is allocated for the font pattern and the its strings.
+ *
+ *---------------------------------------------------------------------------
+ */
+static TkFontPattern *
+TkParseTkDesc(Tcl_Interp *interp, int objc, Tcl_Obj **objv)
+{
+ TkFontPattern *patternPtr;
+ Tcl_Obj **aobjv;
+ int aobjc;
+ int i;
+
+ patternPtr = TkNewFontPattern();
+
+ /* Font family. */
+ {
+ char *family, *dash;
+ family = Tcl_GetString(objv[0]);
+ dash = strchr(family, '-');
+ if (dash != NULL) {
+ int size;
+
+ if (Tcl_GetInt(NULL, dash + 1, &size) != TCL_OK) {
+ goto error;
+ }
+ patternPtr->size = size;
+ }
+ if (dash != NULL) {
+ *dash = '\0';
+ }
+ patternPtr->family = Blt_Strdup(GetAlias(family));
+ if (dash != NULL) {
+ *dash = '-';
+ i = 1;
+ }
+ objv++, objc--;
+ }
+ if (objc > 0) {
+ int size;
+
+ if (Tcl_GetIntFromObj(NULL, objv[0], &size) == TCL_OK) {
+ patternPtr->size = size;
+ objv++, objc--;
+ }
+ }
+ aobjc = objc, aobjv = objv;
+ if (objc > 0) {
+ if (Tcl_ListObjGetElements(NULL, objv[0], &aobjc, &aobjv) != TCL_OK) {
+ goto error;
+ }
+ }
+ for (i = 0; i < aobjc; i++) {
+ FontSpec *specPtr;
+ const char *key;
+
+ key = Tcl_GetString(aobjv[i]);
+ specPtr = FindSpec(interp, fontSpecs, nFontSpecs, key);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ if (specPtr->key == NULL) {
+ continue;
+ }
+ if (strcmp(specPtr->key, FC_WEIGHT) == 0) {
+ patternPtr->weight = specPtr->oldvalue;
+ } else if (strcmp(specPtr->key, FC_SLANT) == 0) {
+ patternPtr->slant = specPtr->oldvalue;
+ } else if (strcmp(specPtr->key, FC_SPACING) == 0) {
+ patternPtr->spacing = specPtr->oldvalue;
+ } else if (strcmp(specPtr->key, FC_WIDTH) == 0) {
+ patternPtr->width = specPtr->oldvalue;
+ }
+ }
+ return patternPtr;
+ error:
+ TkFreeFontPattern(patternPtr);
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkParseNameValuePairs --
+ *
+ * Given Tcl_Obj list of name value pairs, parse the list saving
+ * in the values in a font pattern structure.
+ *
+ * "-family family -size size -weight weight"
+ *
+ * Results:
+ * Returns a pattern structure, filling in with the necessary fields.
+ * Returns NULL if objv doesn't contain a valid name-value list
+ * describing a font.
+ *
+ * Side effects:
+ * Memory is allocated for the font pattern and the its strings.
+ *
+ *---------------------------------------------------------------------------
+ */
+static TkFontPattern *
+TkParseNameValuePairs(Tcl_Interp *interp, Tcl_Obj *objPtr)
+{
+ TkFontPattern *patternPtr;
+ Tcl_Obj **objv;
+ int objc;
+ int i;
+
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) ||
+ (objc < 1)) {
+ return NULL; /* Can't split list or list is empty. */
+ }
+ if (objc & 0x1) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "odd number of elements, missing value",
+ (char *)NULL);
+ }
+ return NULL; /* Odd number of elements in list. */
+ }
+ patternPtr = TkNewFontPattern();
+ for (i = 0; i < objc; i += 2) {
+ const char *key, *value;
+
+ key = Tcl_GetString(objv[i]);
+ value = Tcl_GetString(objv[i+1]);
+ if (strcmp(key, "-family") == 0) {
+ if (patternPtr->family != NULL) {
+ free(patternPtr->family);
+ }
+ patternPtr->family = Blt_Strdup(GetAlias(value));
+ } else if (strcmp(key, "-size") == 0) {
+ int size;
+
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &size) != TCL_OK) {
+ goto error;
+ }
+ patternPtr->size = size;
+ } else if (strcmp(key, "-weight") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, weightSpecs, nWeightSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ patternPtr->weight = specPtr->oldvalue;
+ } else if (strcmp(key, "-slant") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, slantSpecs, nSlantSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ patternPtr->slant = specPtr->oldvalue;
+ } else if (strcmp(key, "-spacing") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, spacingSpecs, nSpacingSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ patternPtr->spacing = specPtr->oldvalue;
+ } else if (strcmp(key, "-hint") == 0) {
+ /* Ignore */
+ } else if (strcmp(key, "-rgba") == 0) {
+ /* Ignore */
+ } else if (strcmp(key, "-underline") == 0) {
+ /* Ignore */
+ } else if (strcmp(key, "-overstrike") == 0) {
+ /* Ignore */
+ } else {
+ /* Ignore */
+ }
+ }
+ return patternPtr;
+ error:
+ TkFreeFontPattern(patternPtr);
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkParseNameValuePairs --
+ *
+ * Given the name of a Tk font object, get its configuration values
+ * save the data in a font pattern structure.
+ *
+ * "-family family -size size -weight weight"
+ *
+ * Results:
+ * Returns a pattern structure, filling in with the necessary fields.
+ * Returns NULL if objv doesn't contain a valid name-value list
+ * describing a font.
+ *
+ * Side effects:
+ * Memory is allocated for the font pattern and the its strings.
+ *
+ *---------------------------------------------------------------------------
+ */
+static TkFontPattern *
+TkParseFontObj(Tcl_Interp *interp, Tcl_Obj *objPtr)
+{
+ TkFontPattern *patternPtr;
+ Tcl_Obj *cmd[3];
+ int result;
+
+ patternPtr = NULL;
+ cmd[0] = Tcl_NewStringObj("font", -1);
+ cmd[1] = Tcl_NewStringObj("configure", -1);
+ cmd[2] = objPtr;
+ Tcl_IncrRefCount(cmd[0]);
+ Tcl_IncrRefCount(cmd[1]);
+ Tcl_IncrRefCount(cmd[2]);
+ result = Tcl_EvalObjv(interp, 3, cmd, 0);
+ Tcl_DecrRefCount(cmd[2]);
+ Tcl_DecrRefCount(cmd[1]);
+ Tcl_DecrRefCount(cmd[0]);
+ if (result == TCL_OK) {
+ patternPtr = TkParseNameValuePairs(interp, Tcl_GetObjResult(interp));
+ }
+ Tcl_ResetResult(interp);
+ return patternPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkGetPattern --
+ *
+ * Parses the font description so that the font can rewritten with an
+ * aliased font name. This allows us to use
+ *
+ * "Sans Serif", "Serif", "Math", "Monospace"
+ *
+ * font names that correspond to the proper font regardless if the
+ * standard X fonts or XFT fonts are being used.
+ *
+ * Leave XLFD font descriptions alone. Let users describe exactly the
+ * font they wish.
+ *
+ *---------------------------------------------------------------------------
+ */
+static TkFontPattern *
+TkGetPattern(Tcl_Interp *interp, Tcl_Obj *objPtr)
+{
+ TkFontPattern *patternPtr;
+ char *desc;
+
+ desc = Tcl_GetString(objPtr);
+ while (isspace(*desc)) {
+ desc++; /* Skip leading blanks. */
+ }
+ if (*desc == '-') {
+ /*
+ * Case 1: XLFD font description or Tk attribute list.
+ *
+ * If the font description starts with a '-', it could be either an
+ * old fashion XLFD font description or a Tk font attribute
+ * option-value list.
+ */
+ patternPtr = TkParseNameValuePairs(interp, objPtr);
+ if (patternPtr == NULL) {
+ return NULL; /* XLFD font description */
+ }
+ } else if (*desc == '*') {
+ return NULL; /* XLFD font description */
+ } else if (strpbrk(desc, "::") != NULL) {
+ patternPtr = TkParseFontObj(interp, objPtr);
+ } else {
+ int objc;
+ Tcl_Obj **objv;
+ /*
+ * Case 3: Tk-style description.
+ */
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) ||
+ (objc < 1)) {
+ return NULL; /* Can't split into a list or
+ * list is empty. */
+ }
+ patternPtr = NULL;
+ if (objc == 1) {
+ /*
+ * Case 3a: Tk font object name.
+ *
+ * Assuming that Tk font object names won't contain whitespace,
+ * see if its a font object.
+ */
+ patternPtr = TkParseFontObj(interp, objv[0]);
+ }
+ if (patternPtr == NULL) {
+ /*
+ * Case 3b: List of font attributes in the form "family size
+ * ?attrs?"
+ */
+ patternPtr = TkParseTkDesc(interp, objc, objv);
+ }
+ }
+ return patternPtr;
+}
+
+static void
+TkWriteXLFDDescription(Tk_Window tkwin, TkFontPattern *patternPtr,
+ Tcl_DString *resultPtr)
+{
+ const char *string;
+ int size;
+
+ /* Rewrite the font description using the aliased family. */
+ Tcl_DStringInit(resultPtr);
+
+ /* Foundry */
+ Tcl_DStringAppend(resultPtr, "-*-", 3);
+ /* Family */
+ string = (patternPtr->family != NULL) ? patternPtr->family : "*";
+ Tcl_DStringAppend(resultPtr, string, -1);
+ Tcl_DStringAppend(resultPtr, "-", 1);
+ /* Weight */
+ string = (patternPtr->weight == NULL) ? "*" : patternPtr->weight;
+ Tcl_DStringAppend(resultPtr, string, -1);
+ Tcl_DStringAppend(resultPtr, "-", 1);
+ /* Slant */
+ string = (patternPtr->slant == NULL) ? "*" : patternPtr->slant;
+ Tcl_DStringAppend(resultPtr, string, -1);
+ Tcl_DStringAppend(resultPtr, "-", 1);
+ /* Width */
+ string = (patternPtr->width == NULL) ? "*" : patternPtr->width;
+ Tcl_DStringAppend(resultPtr, string, -1);
+ /* Style */
+ Tcl_DStringAppend(resultPtr, "-*-", 3);
+ /* Pixel size */
+ size = (int)(PointsToPixels(tkwin, patternPtr->size) + 0.5);
+ string = (size == 0) ? "*" : Blt_Itoa(size);
+ Tcl_DStringAppend(resultPtr, string, -1);
+ /* Point size */
+ Tcl_DStringAppend(resultPtr, "-", 1);
+ size = (int)(PixelsToPoints(tkwin, patternPtr->size) + 0.5);
+ string = (size == 0) ? "*" : Blt_Itoa(size);
+ Tcl_DStringAppend(resultPtr, string, -1);
+
+ /* resx, resy */
+ Tcl_DStringAppend(resultPtr, "-*-*-", 5);
+ /* Spacing */
+ string = (patternPtr->spacing == NULL) ? "*" : patternPtr->spacing;
+ Tcl_DStringAppend(resultPtr, string, -1);
+ /* Average Width, Registry, Encoding */
+ Tcl_DStringAppend(resultPtr, "-*-*-*-", 7);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkGetFontFromObj --
+ *
+ * Opens a Tk font based on the description in the Tcl_Obj. We first
+ * parse the description and if necessary rewrite it using the proper
+ * font aliases. The font names
+ *
+ * "Sans Serif", "Serif", "Math", "Monospace"
+ *
+ * correspond to the proper font regardless if the standard X fonts or
+ * XFT fonts are being used.
+ *
+ * Leave XLFD font descriptions alone. Let users describe exactly the
+ * font they wish.
+ *
+ * Outside of reimplementing the Tk font mechanism, rewriting the
+ * font allows use to better handle programs that must work with
+ * X servers with and without the XRender extension. It means
+ * that the widget's default font settings do not have to use
+ * XLFD fonts even if XRender is available.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Tk_Font
+TkGetFontFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ Tk_Font tkFont;
+ TkFontPattern *patternPtr;
+
+ if (!alias_initialized) {
+ MakeAliasTable(tkwin);
+ alias_initialized++;
+ }
+ patternPtr = TkGetPattern(interp, objPtr);
+ if (patternPtr == NULL) {
+ tkFont = Tk_GetFont(interp, tkwin, Tcl_GetString(objPtr));
+ } else {
+ Tcl_DString ds;
+
+ /* Rewrite the font description using the aliased family. */
+ TkWriteXLFDDescription(tkwin, patternPtr, &ds);
+ tkFont = Tk_GetFont(interp, tkwin, Tcl_DStringValue(&ds));
+ Tcl_DStringFree(&ds);
+ TkFreeFontPattern(patternPtr);
+ }
+ return tkFont;
+}
+
+static const char *
+TkNameOfFontProc(_Blt_Font *fontPtr)
+{
+ return Tk_NameOfFont(fontPtr->clientData);
+}
+
+static const char *
+TkFamilyOfFontProc(_Blt_Font *fontPtr)
+{
+ return ((TkFont *)fontPtr->clientData)->fa.family;
+}
+
+static Font
+TkFontIdProc(_Blt_Font *fontPtr)
+{
+ return Tk_FontId(fontPtr->clientData);
+}
+
+static void
+TkGetFontMetricsProc(_Blt_Font *fontPtr, Blt_FontMetrics *fmPtr)
+{
+ TkFont *tkFontPtr = fontPtr->clientData;
+ Tk_FontMetrics fm;
+
+ Tk_GetFontMetrics(fontPtr->clientData, &fm);
+ fmPtr->ascent = fm.ascent;
+ fmPtr->descent = fm.descent;
+ fmPtr->linespace = fm.linespace;
+ fmPtr->tabWidth = tkFontPtr->tabWidth;
+ fmPtr->underlinePos = tkFontPtr->underlinePos;
+ fmPtr->underlineHeight = tkFontPtr->underlineHeight;
+}
+
+static int
+TkMeasureCharsProc(_Blt_Font *fontPtr, const char *text, int nBytes, int max,
+ int flags, int *lengthPtr)
+{
+ return Tk_MeasureChars(fontPtr->clientData, text, nBytes, max, flags,
+ lengthPtr);
+}
+
+static int
+TkTextStringWidthProc(_Blt_Font *fontPtr, const char *string, int nBytes)
+{
+ return Tk_TextWidth(fontPtr->clientData, string, nBytes);
+}
+
+static void
+TkDrawCharsProc(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing characters. */
+ _Blt_Font *fontPtr, /* Font in which characters will be drawn;
+ * must be the same as font used in GC. */
+ int depth, /* Not used. */
+ float angle, /* Not used. */
+ const char *text, /* UTF-8 string to be displayed. Need not be
+ * '\0' terminated. All Tk meta-characters
+ * (tabs, control characters, and newlines)
+ * should be stripped out of the string that
+ * is passed to this function. If they are
+ * not stripped out, they will be displayed as
+ * regular printing characters. */
+ int nBytes, /* Number of bytes in string. */
+ int x, int y) /* Coordinates at which to place origin of
+ * string when drawing. */
+{
+ Tk_DrawChars(display, drawable, gc, fontPtr->clientData,text, nBytes, x, y);
+}
+
+static int
+TkPostscriptFontNameProc(_Blt_Font *fontPtr, Tcl_DString *resultPtr)
+{
+ TkFont *tkFontPtr;
+ unsigned int flags;
+
+ tkFontPtr = (TkFont *)fontPtr->clientData;
+ flags = 0;
+ if (tkFontPtr->fa.slant != TK_FS_ROMAN) {
+ flags |= FONT_ITALIC;
+ }
+ if (tkFontPtr->fa.weight != TK_FW_NORMAL) {
+ flags |= FONT_BOLD;
+ }
+ Blt_Ps_FontName(tkFontPtr->fa.family, flags, resultPtr);
+ return tkFontPtr->fa.size;
+}
+
+static int
+TkCanRotateFontProc(_Blt_Font *fontPtr, float angle)
+{
+ return FALSE;
+}
+
+static void
+TkFreeFontProc(_Blt_Font *fontPtr)
+{
+ Tk_FreeFont(fontPtr->clientData);
+ free(fontPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * TkUnderlineCharsProc --
+ *
+ * This procedure draws an underline for a given range of characters in a
+ * given string. It doesn't draw the characters (which are assumed to
+ * have been displayed previously); it just draws the underline. This
+ * procedure would mainly be used to quickly underline a few characters
+ * without having to construct an underlined font. To produce properly
+ * underlined text, the appropriate underlined font should be constructed
+ * and used.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets displayed in "drawable".
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+TkUnderlineCharsProc(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for actually drawing
+ * line. */
+ _Blt_Font *fontPtr, /* Font used in GC; must have been
+ * allocated by Tk_GetFont(). Used for
+ * character dimensions, etc. */
+ const char *text, /* String containing characters to be
+ * underlined or overstruck. */
+ int textLen, /* Unused. */
+ int x, int y, /* Coordinates at which first character of
+ * string is drawn. */
+ int first, /* Byte offset of the first character. */
+ int last, /* Byte offset after the last character. */
+ int xMax)
+{
+ Tk_UnderlineChars(display, drawable, gc, fontPtr->clientData, text, x, y,
+ first, last);
+}
+
+#ifdef HAVE_LIBXFT
+
+static Blt_NameOfFontProc FtNameOfFontProc;
+static Blt_FamilyOfFontProc FtFamilyOfFontProc;
+static Blt_FontIdProc FtFontIdProc;
+static Blt_GetFontMetricsProc FtGetFontMetricsProc;
+static Blt_MeasureCharsProc FtMeasureCharsProc;
+static Blt_TextStringWidthProc FtTextStringWidthProc;
+static Blt_FreeFontProc FtFreeFontProc;
+static Blt_DrawCharsProc FtDrawCharsProc;
+static Blt_PostscriptFontNameProc FtPostscriptFontNameProc;
+static Blt_CanRotateFontProc FtCanRotateFontProc;
+static Blt_UnderlineCharsProc FtUnderlineCharsProc;
+
+static Blt_FontClass ftFontClass = {
+ FONT_FT,
+ FtNameOfFontProc, /* Blt_NameOfFontProc */
+ FtFamilyOfFontProc, /* Blt_FamilyOfFontProc */
+ FtFontIdProc, /* Blt_FontIdProc */
+ FtGetFontMetricsProc, /* Blt_GetFontMetricsProc */
+ FtMeasureCharsProc, /* Blt_MeasureCharsProc */
+ FtTextStringWidthProc, /* Blt_TextStringWidthProc */
+ FtCanRotateFontProc, /* Blt_CanRotateFontProc */
+ FtDrawCharsProc, /* Blt_DrawCharsProc */
+ FtPostscriptFontNameProc, /* Blt_PostscriptFontNameProc */
+ FtFreeFontProc, /* Blt_FreeFontProc */
+ FtUnderlineCharsProc, /* Blt_UnderlineCharsProc */
+};
+
+/*
+ * Freetype font container.
+ */
+typedef struct {
+ char *name; /* Name of the font (malloc-ed). */
+ int refCount; /* Reference count for this structure.
+ * When refCount reaches zero, it
+ * means to free the resources
+ * associated with this structure. */
+ Blt_HashEntry *hashPtr; /* Pointer to this entry in global
+ * font hash table. Used to remove the
+ * entry * from the table. */
+ Font fid; /* Font id used to fake out
+ * Tk_FontId. */
+ FcPattern *pattern; /* Pattern matching the current
+ * non-rotated font. Used to create
+ * rotated fonts by duplicating the
+ * pattern and adding a rotation
+ * matrix. */
+
+ Blt_HashTable fontTable; /* Hash table containing an Xft font
+ * for each angle it's used at. Will
+ * always contain a 0 degree
+ * entry. */
+
+ /* Information specific to the display/drawable being used. The drawables
+ * are changed as the drawable changes for each drawing request.
+ * Typically this will change for each pixmap. */
+
+ Drawable drawable; /* Drawable associated with draw. */
+ XftDraw *draw; /* Current Xft drawable. */
+ int drawDepth; /* Depth of current drawable. */
+
+ XftColor color; /* Color to be displayed. We don't
+ * actually allocate this color, since
+ * we assume it's been already
+ * allocated by the standard Tk
+ * procedures. */
+
+ /* Saved Information from the Tk_Window used to created the initial
+ * font. */
+ Display *display;
+ Visual *visual;
+ int screenNum;
+ Colormap colormap;
+
+ int underlineHeight; /* Thickness of underline
+ * rectangle. */
+ int underlinePos; /* Offset of underline. */
+ int tabWidth;
+} FtFont;
+
+static FontSpec rgbaSpecs[] = {
+ { "bgr", 1, FC_RGBA, FC_RGBA_BGR, },
+ { "none", 1, FC_RGBA, FC_RGBA_NONE, },
+ { "rgb", 1, FC_RGBA, FC_RGBA_RGB, },
+ { "unknown", 1, FC_RGBA, FC_RGBA_UNKNOWN, },
+ { "vbgr", 2, FC_RGBA, FC_RGBA_VBGR, },
+ { "vrgb", 2, FC_RGBA, FC_RGBA_VRGB, },
+};
+static int nRgbaSpecs = sizeof(rgbaSpecs) / sizeof(FontSpec);
+
+static FontSpec hintSpecs[] = {
+ { "full", 1, FC_HINT_STYLE, FC_HINT_FULL, },
+ { "medium", 1, FC_HINT_STYLE, FC_HINT_MEDIUM, },
+ { "none", 1, FC_HINT_STYLE, FC_HINT_NONE, },
+ { "slight", 1, FC_HINT_STYLE, FC_HINT_SLIGHT, },
+};
+static int nHintSpecs = sizeof(hintSpecs) / sizeof(FontSpec);
+
+static void
+FtGetFontFamilies(Tk_Window tkwin, Blt_HashTable *tablePtr)
+{
+ XftFontSet *fsPtr;
+ int i;
+
+ fsPtr = XftListFonts(Tk_Display(tkwin),
+ Tk_ScreenNumber(tkwin),
+ (char*)NULL, /* pattern elements */
+ XFT_FAMILY, (char*)NULL); /* fields */
+ for (i = 0; i < fsPtr->nfont; i++) {
+ FcResult result;
+ FcChar8 *family;
+
+ result = FcPatternGetString(fsPtr->fonts[i], FC_FAMILY, 0, &family);
+ if (result == FcResultMatch) {
+ int isNew;
+ char *name;
+
+ /* Family names must be all lower case in the hash table. */
+ name = Blt_Strdup((const char *)family);
+ strtolower(name);
+ Blt_CreateHashEntry(tablePtr, name, &isNew);
+ free(name);
+ }
+ }
+ XftFontSetDestroy(fsPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FtParseTkDesc --
+ *
+ * Try to open a Xft font from an Tk style font description.
+ *
+ * Results:
+ * Return value is TCL_ERROR if string was not a fully specified XLFD.
+ * Otherwise, fills font attribute buffer with the values parsed from the
+ * XLFD and returns TCL_OK.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static FcPattern *
+FtParseTkDesc(Tcl_Interp *interp, Tk_Window tkwin, int objc, Tcl_Obj **objv)
+{
+ FcPattern *pattern;
+ int i;
+ const char *family;
+
+ pattern = FcPatternCreate();
+ FcPatternAddBool(pattern, FC_ANTIALIAS, FcTrue);
+
+ /* Font family. */
+ family = GetAlias(Tcl_GetString(objv[0]));
+ FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *)family);
+
+ /* Size */
+ if (objc > 1) {
+ int size;
+
+ if (Tcl_GetIntFromObj(NULL, objv[1], &size) != TCL_OK) {
+ goto error;
+ }
+ FcPatternAddDouble(pattern, FC_SIZE, PixelsToPoints(tkwin, size));
+ }
+ i = 2;
+ if (objc == 3) {
+ if (Tcl_ListObjGetElements(interp, objv[2], &objc, &objv) != TCL_OK) {
+ goto error;
+ }
+ i = 0;
+ }
+ for (/*empty*/; i < objc; i++) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, fontSpecs, nFontSpecs,
+ Tcl_GetString(objv[i]));
+ if (specPtr == NULL) {
+ goto error;
+ }
+ if (specPtr->key != NULL) {
+ FcPatternAddInteger(pattern, specPtr->key, specPtr->value);
+ }
+ }
+ return pattern;
+ error:
+ if (pattern != NULL) {
+ FcPatternDestroy(pattern);
+ }
+ return NULL;
+}
+
+static FcPattern *
+FtParseTkFontAttributeList(Tcl_Interp *interp, Tk_Window tkwin,
+ Tcl_Obj *objPtr)
+{
+ FcPattern *pattern;
+ Tcl_Obj **objv;
+ int objc;
+ int i;
+
+ if ((Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) ||
+ (objc < 1)) {
+ return NULL; /* Can't split list or list is empty. */
+ }
+ if (objc & 0x1) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "odd number of elements, missing value",
+ (char *)NULL);
+ }
+ return NULL; /* Odd number of elements in list. */
+ }
+ pattern = FcPatternCreate();
+ FcPatternAddBool(pattern, FC_ANTIALIAS, FcTrue);
+ for (i = 0; i < objc; i += 2) {
+ char *key, *value;
+
+ key = Tcl_GetString(objv[i]);
+ value = Tcl_GetString(objv[i+1]);
+ if (strcmp(key, "-family") == 0) {
+ const char *family;
+
+ family = GetAlias(value);
+ FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *)family);
+ } else if (strcmp(key, "-size") == 0) {
+ int size;
+
+ if (Tcl_GetIntFromObj(interp, objv[i+1], &size) != TCL_OK) {
+ goto error;
+ }
+ FcPatternAddDouble(pattern, FC_SIZE, PixelsToPoints(tkwin, size));
+ } else if (strcmp(key, "-weight") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, weightSpecs, nWeightSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_WEIGHT, specPtr->value);
+ } else if (strcmp(key, "-slant") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, slantSpecs, nSlantSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_SLANT, specPtr->value);
+ } else if (strcmp(key, "-hint") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, hintSpecs, nHintSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_HINT_STYLE, specPtr->value);
+ } else if (strcmp(key, "-rgba") == 0) {
+ FontSpec *specPtr;
+
+ specPtr = FindSpec(interp, rgbaSpecs, nRgbaSpecs, value);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_RGBA, specPtr->value);
+ } else if (strcmp(key, "-underline") == 0) {
+ /* Ignore */
+ } else if (strcmp(key, "-overstrike") == 0) {
+ /* Ignore */
+ } else {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown switch \"", key,
+ "\" in font description.", (char *)NULL);
+ }
+ goto error;
+ }
+ }
+ return pattern;
+ error:
+ FcPatternDestroy(pattern);
+ return NULL;
+}
+
+static FcPattern *
+FtGetAttributesFromFontObj(Tk_Window tkwin, Tcl_Interp *interp,
+ Tcl_Obj *objPtr)
+{
+ FcPattern *pattern;
+ Tcl_Obj *cmd[3];
+ int result;
+
+ cmd[0] = Tcl_NewStringObj("font", -1);
+ cmd[1] = Tcl_NewStringObj("configure", -1);
+ cmd[2] = objPtr;
+ result = Blt_GlobalEvalObjv(interp, 3, cmd);
+ if (result == TCL_OK) {
+ pattern = FtParseTkFontAttributeList(interp, tkwin,
+ Tcl_GetObjResult(interp));
+ } else {
+ pattern = NULL;
+ }
+ Tcl_ResetResult(interp);
+ return pattern;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FtParseXLFD --
+ *
+ * Try to open a Xft font from an XLFD description.
+ *
+ * Results:
+ * Return value is TCL_ERROR if string was not a fully specified XLFD.
+ * Otherwise, fills font attribute buffer with the values parsed from the
+ * XLFD and returns TCL_OK.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static FcPattern *
+FtParseXLFD(Tcl_Interp *interp, Tk_Window tkwin, char *fontName)
+{
+ FcPattern *pattern;
+ FontSpec *specPtr;
+ int argc;
+ char **argv;
+ double size;
+
+ if (fontName[0] == '-') {
+ fontName++;
+ }
+ ParseXLFD(fontName, &argc, &argv);
+
+ pattern = FcPatternCreate();
+ FcPatternAddBool(pattern, FC_ANTIALIAS, FcTrue);
+
+ if (argv[XLFD_FOUNDRY] != NULL) {
+ FcPatternAddString(pattern, FC_FOUNDRY,
+ (const FcChar8 *)argv[XLFD_FOUNDRY]);
+ }
+ if (argv[XLFD_FAMILY] != NULL) {
+ FcPatternAddString(pattern, FC_FAMILY,
+ (const FcChar8 *)argv[XLFD_FAMILY]);
+ }
+ if (argv[XLFD_WEIGHT] != NULL) {
+ specPtr = FindSpec(interp, weightSpecs, nWeightSpecs,
+ argv[XLFD_WEIGHT]);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_WEIGHT, specPtr->value);
+ }
+ if (argv[XLFD_SLANT] != NULL) {
+ specPtr = FindSpec(interp, slantSpecs, nSlantSpecs, argv[XLFD_SLANT]);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_SLANT, specPtr->value);
+ }
+ if (argv[XLFD_SETWIDTH] != NULL) {
+ specPtr = FindSpec(interp, widthSpecs, nWidthSpecs,
+ argv[XLFD_SETWIDTH]);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_WIDTH, specPtr->value);
+ }
+ if (argv[XLFD_ADD_STYLE] != NULL) {
+ FcPatternAddString(pattern, FC_STYLE,
+ (const FcChar8 *)argv[XLFD_ADD_STYLE]);
+ }
+ size = 12.0;
+ if (argv[XLFD_PIXEL_SIZE] != NULL) {
+ int value;
+ if (argv[XLFD_PIXEL_SIZE][0] == '[') {
+ /*
+ * Some X fonts have the point size specified as follows:
+ *
+ * [ N1 N2 N3 N4 ]
+ *
+ * where N1 is the point size (in points, not decipoints!), and
+ * N2, N3, and N4 are some additional numbers that I don't know
+ * the purpose of, so I ignore them.
+ */
+ value = atoi(argv[XLFD_PIXEL_SIZE]+1);
+ } else if (Tcl_GetInt(NULL, argv[XLFD_PIXEL_SIZE], &value) == TCL_OK) {
+ /* empty */
+ } else {
+ goto error;
+ }
+ size = PixelsToPoints(tkwin, -value);
+ }
+
+ if (argv[XLFD_POINT_SIZE] != NULL) {
+ int value;
+ if (argv[XLFD_POINT_SIZE][0] == '[') {
+ /*
+ * Some X fonts have the point size specified as follows:
+ *
+ * [ N1 N2 N3 N4 ]
+ *
+ * where N1 is the point size (in points, not decipoints!), and
+ * N2, N3, and N4 are some additional numbers that I don't know
+ * the purpose of, so I ignore them.
+ */
+ value = atoi(argv[XLFD_POINT_SIZE]+1);
+ } else if (Tcl_GetInt(NULL, argv[XLFD_POINT_SIZE], &value) == TCL_OK) {
+ /* empty */
+ } else {
+ goto error;
+ }
+ size = PixelsToPoints(tkwin, -value) * 0.1;
+ }
+
+ FcPatternAddDouble(pattern, FC_SIZE, (double)size);
+
+ if (argv[XLFD_SPACING] != NULL) {
+ specPtr = FindSpec(interp, spacingSpecs, nSpacingSpecs,
+ argv[XLFD_SPACING]);
+ if (specPtr == NULL) {
+ goto error;
+ }
+ FcPatternAddInteger(pattern, FC_SPACING, specPtr->value);
+ }
+ free((char *)argv);
+ return pattern;
+ error:
+ free((char *)argv);
+ FcPatternDestroy(pattern);
+ return NULL;
+}
+
+
+static void
+FtDeleteFont(FtFont *ftPtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&ftPtr->fontTable, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ XftFont *xftPtr;
+
+ xftPtr = Blt_GetHashValue(hPtr);
+ XftFontClose(ftPtr->display, xftPtr);
+ }
+ Blt_DeleteHashTable(&ftPtr->fontTable);
+
+ if (ftPtr->name != NULL) {
+ free(ftPtr->name);
+ }
+ if (ftPtr->draw != 0) {
+ XftDrawDestroy(ftPtr->draw);
+ }
+ if (ftPtr->fid) {
+ XUnloadFont(ftPtr->display, ftPtr->fid);
+ }
+ Blt_DeleteHashEntry(&fontTable, ftPtr->hashPtr);
+ free(ftPtr);
+}
+
+static int
+FtMeasureChars(FtFont *ftPtr, const char *source, int nBytes, int maxLength,
+ int flags, int *lengthPtr)
+{
+ FcChar32 c;
+ XGlyphInfo extents;
+ int clen;
+ int curX, newX;
+ int termByte = 0, termX = 0;
+ int curByte, newByte, sawNonSpace;
+ XftFont *xftPtr;
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&ftPtr->fontTable, (char *)0L);
+ if (hPtr == NULL) {
+ return 0;
+ }
+ xftPtr = Blt_GetHashValue(hPtr);
+ curX = 0;
+ curByte = 0;
+ sawNonSpace = 0;
+ while (nBytes > 0) {
+ Tcl_UniChar unichar;
+
+ clen = Tcl_UtfToUniChar(source, &unichar);
+ c = (FcChar32)unichar;
+
+ if (clen <= 0) {
+ /* This can't happen (but see #1185640) */
+ *lengthPtr = curX;
+ return curByte;
+ }
+
+ source += clen;
+ nBytes -= clen;
+ if (c < 256 && isspace(c)) { /* I18N: ??? */
+ if (sawNonSpace) {
+ termByte = curByte;
+ termX = curX;
+ sawNonSpace = 0;
+ }
+ } else {
+ sawNonSpace = 1;
+ }
+
+ XftTextExtents32(ftPtr->display, xftPtr, &c, 1, &extents);
+
+ newX = curX + extents.xOff;
+ newByte = curByte + clen;
+ if (maxLength >= 0 && newX > maxLength) {
+ if ((flags & TK_PARTIAL_OK) ||
+ ((flags & TK_AT_LEAST_ONE && curByte == 0))) {
+ curX = newX;
+ curByte = newByte;
+ } else if ((flags & TK_WHOLE_WORDS) && (termX != 0)) {
+ curX = termX;
+ curByte = termByte;
+ }
+ break;
+ }
+
+ curX = newX;
+ curByte = newByte;
+ }
+ *lengthPtr = curX;
+ return curByte;
+}
+
+static void
+FtSetFontParams(Tk_Window tkwin, FtFont *ftPtr, XftFont *xftPtr)
+{
+ FT_UInt glyph;
+ XGlyphInfo metrics;
+ double size;
+ FcResult result;
+
+ /*
+ * Get information used for drawing underlines from the 0 angle font.
+ */
+ glyph = XftCharIndex(ftPtr->display, xftPtr, '0');
+ XftGlyphExtents(ftPtr->display, xftPtr, &glyph, 1, &metrics);
+
+ ftPtr->underlinePos = xftPtr->descent / 2;
+ result = FcPatternGetDouble(xftPtr->pattern, FC_SIZE, 0, &size);
+ if (result != FcResultMatch) {
+ size = 12.0;
+ }
+ ftPtr->underlineHeight = (int)(PointsToPixels(tkwin,(int)size)/10.0 + 0.5);
+ if (ftPtr->underlineHeight == 0) {
+ ftPtr->underlineHeight = 1;
+ }
+ if ((ftPtr->underlinePos + ftPtr->underlineHeight) > xftPtr->descent) {
+ /*
+ * If this set of values would cause the bottom of the underline bar
+ * to stick below the descent of the font, jack the underline up a bit
+ * higher.
+ */
+ ftPtr->underlineHeight = xftPtr->descent - ftPtr->underlinePos;
+ if (ftPtr->underlineHeight == 0) {
+ ftPtr->underlinePos--;
+ ftPtr->underlineHeight = 1;
+ }
+ }
+ FtMeasureChars(ftPtr, "0", 1, -1, 0, &ftPtr->tabWidth);
+ if (ftPtr->tabWidth == 0) {
+ ftPtr->tabWidth = xftPtr->max_advance_width;
+ }
+ ftPtr->tabWidth *= 8;
+ /*
+ * Make sure the tab width isn't zero (some fonts may not have enough
+ * information to set a reasonable tab width).
+ */
+ if (ftPtr->tabWidth == 0) {
+ ftPtr->tabWidth = 1;
+ }
+}
+
+static FtFont *
+FtNewFont(Tcl_Interp *interp, Tk_Window tkwin, const char *fontName,
+ XftFont *xftPtr)
+{
+ Blt_HashEntry *hPtr;
+ FtFont *ftPtr;
+ int isNew;
+
+ ftPtr = calloc(1, sizeof(FtFont));
+ ftPtr->name = Blt_Strdup(fontName);
+ ftPtr->visual = Tk_Visual(tkwin);
+ ftPtr->colormap = Tk_Colormap(tkwin);
+ ftPtr->display = Tk_Display(tkwin);
+ ftPtr->fid = XLoadFont(Tk_Display(tkwin), "fixed");
+ ftPtr->color.pixel = 0xFFFFFFFF;
+ ftPtr->pattern = xftPtr->pattern;
+ ftPtr->refCount = 1;
+ /*
+ * Initialize the Xft font table for this font. Add the initial Xft font
+ * for the case of 0 degrees rotation.
+ */
+ Blt_InitHashTable(&ftPtr->fontTable, BLT_ONE_WORD_KEYS);
+ hPtr = Blt_CreateHashEntry(&ftPtr->fontTable, (char *)0L, &isNew);
+ assert(isNew);
+ Blt_SetHashValue(hPtr, xftPtr);
+
+ /* Add the font information to the font table. */
+ hPtr = Blt_CreateHashEntry(&fontTable, fontName, &isNew);
+ assert(isNew);
+ Blt_SetHashValue(hPtr, ftPtr);
+ ftPtr->hashPtr = hPtr;
+ FtSetFontParams(tkwin, ftPtr, xftPtr);
+ return ftPtr;
+}
+
+/*
+ * FtGetPattern --
+ *
+ * Generates an pattern based upon the font description provided. The
+ * description is parsed base upon Tk's font selection rules (listed
+ * below).
+ *
+ * Tk's Font Selection Rules:
+ *
+ * When font description font is used, the system attempts to parse the
+ * description according to each of the above five rules, in the order
+ * specified. Cases [1] and [2] must match the name of an existing named
+ * font or of a system font. Cases [3], [4], and [5] are accepted on all
+ * platforms and the closest available font will be used. In some
+ * situations it may not be possible to find any close font (e.g., the
+ * font family was a garbage value); in that case, some system-dependant
+ * default font is chosen. If the font description does not match any of
+ * the above patterns, an error is generated.
+ *
+ * [1] fontname
+ * The name of a named font, created using the font create command. When
+ * a widget uses a named font, it is guaranteed that this will never
+ * cause an error, as long as the named font exists, no mat- ter what
+ * potentially invalid or meaningless set of attributes the named font
+ * has. If the named font cannot be displayed with exactly the specified
+ * attributes, some other close font will be substituted automatically.
+ *
+ * [Query the named font (using "font configure") and generate an Xft
+ * font with the same attributes. It's assumed that these names don't
+ * start with a '*' or '-'.]
+ *
+ * [2] systemfont
+ * The platform-specific name of a font, interpreted by the graphics
+ * server. This also includes, under X, an XLFD (see [4]) for which a
+ * single ``*'' character was used to elide more than one field in the
+ * middle of the name. See PLATFORM-SPECIFIC issues for a list of the
+ * system fonts.
+ *
+ * [Same as above. Query the named font (using "font configure") and
+ * generate an Xft font with the same attributes.]
+ *
+ * [3] family ?size? ?style? ?style ...?
+ * A properly formed list whose first element is the desired font family
+ * and whose optional second element is the desired size. The
+ * interpretation of the size attribute follows the same rules described
+ * for -size in FONT OPTIONS below. Any additional optional arguments
+ * following the size are font styles. Possible values for the style
+ * arguments are as follows:
+ *
+ * normal, bold, roman, italic, underline, overstrike
+ *
+ * [Parse the list of attributes and generate a corresponding Xft font.]
+ *
+ * [4] X-font names (XLFD)
+ * A Unix-centric font name of the form -foundry-family-weight
+ * slant-setwidth-addstyle-pixel-point-resx-resy-spacing-width
+ * charset-encoding. The ``*'' character may be used to skip indi vidual
+ * fields that the user does not care about. There must be exactly one
+ * ``*'' for each field skipped, except that a ``*'' at the end of the
+ * XLFD skips any remaining fields; the shortest valid XLFD is simply
+ * ``*'', signifying all fields as defaults. Any fields that were
+ * skipped are given default values. For compatibility, an XLFD always
+ * chooses a font of the specified pixel size (not point size); although
+ * this interpretation is not strictly correct, all existing applications
+ * using XLFDs assumed that one ``point'' was in fact one pixel and would
+ * display incorrectly (generally larger) if the correct size font were
+ * actually used.
+ *
+ * [Parse the font description and generate a corresponding Xft font.]
+ *
+ * [5] option value ?option value ...?
+ * A properly formed list of option-value pairs that specify the desired
+ * attributes of the font, in the same format used when defining a named
+ * font.
+ *
+ * [Parse the option-value list and generate a corresponding Xft font.]
+ *
+ * Extra:
+ * [6] Xft font description.
+ *
+ * [Handle the newer Xft font descriptions.]
+ */
+
+static FcPattern *
+FtGetPattern(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ FcPattern *pattern;
+ char *desc;
+
+ desc = Tcl_GetString(objPtr);
+ while (isspace(*desc)) {
+ desc++; /* Skip leading blanks. */
+ }
+ if (*desc == '-') {
+ /*
+ * Case 1: XLFD font description or Tk attribute list.
+ *
+ * If the font description starts with a '-', it could be either an
+ * old fashion XLFD font description or a Tk font attribute
+ * option-value list.
+ */
+ pattern = FtParseTkFontAttributeList(NULL, tkwin, objPtr);
+ if (pattern == NULL) {
+ /* Try parsing it as an XLFD font description. */
+ pattern = FtParseXLFD(interp, tkwin, desc);
+ }
+ } else if (*desc == '*') {
+ pattern = FtParseXLFD(interp, tkwin, desc);
+ } else if (strpbrk(desc, ":,=") != NULL) {
+ /*
+ * Case 2: XFT font description.
+ *
+ * If the font description contains a ':', '=', or ',' in it, we
+ * assume it's a new XFT font description. We want to allow these
+ * font descriptions too.
+ */
+ pattern = NULL;
+ if (strstr(desc, "::") != NULL) {
+ pattern = FtGetAttributesFromFontObj(tkwin, interp, objPtr);
+ }
+ if (pattern == NULL) {
+ pattern = FcNameParse((const FcChar8 *)desc);
+ }
+ } else {
+ int objc;
+ Tcl_Obj **objv;
+ /*
+ * Case 3: Tk-style description.
+ */
+ if ((Tcl_ListObjGetElements(NULL, objPtr, &objc, &objv) != TCL_OK) ||
+ (objc < 1)) {
+ return NULL; /* Can't split into a list or list is
+ * empty. */
+ }
+ if (objc == 1) {
+ /*
+ * Case 3a: Tk font object name.
+ *
+ * Assuming that Tk font object names won't contain whitespace,
+ * see if its a font object.
+ */
+
+ pattern = FtGetAttributesFromFontObj(tkwin, interp, objv[0]);
+ if (pattern == NULL) {
+ pattern = FcNameParse((const FcChar8 *)desc);
+ }
+ } else {
+ /*
+ * Case 3b: List of font attributes in the form "family size
+ * ?attrs?"
+ */
+ pattern = FtParseTkDesc(interp, tkwin, objc, objv);
+ }
+ }
+ return pattern;
+}
+
+static FcPattern *
+FtGetFontPattern(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ FcPattern *pattern;
+
+ pattern = FtGetPattern(interp, tkwin, objPtr);
+ if (pattern != NULL) {
+ FcPattern *match;
+ FcResult result;
+
+ /*
+ * XftFontMatch only sets *result* on complete match failures. So
+ * initialize it here for a successful match. We'll accept partial
+ * matches.
+ */
+ result = FcResultMatch;
+ match = XftFontMatch(Tk_Display(tkwin), Tk_ScreenNumber(tkwin),
+ pattern, &result);
+ FcPatternDestroy(pattern);
+ if ((match != NULL) && (result == FcResultMatch)) {
+ return match;
+ }
+ }
+ return NULL;
+}
+
+static XftFont *
+FtOpenFont(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ FcPattern *pattern;
+
+ pattern = FtGetFontPattern(interp, tkwin, objPtr);
+ if (pattern != NULL) {
+ return XftFontOpenPattern(Tk_Display(tkwin), pattern);
+ }
+ return NULL;
+}
+
+static FtFont *
+FtGetFontFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr)
+{
+ Blt_HashEntry *hPtr;
+ char *desc;
+
+ desc = Tcl_GetString(objPtr);
+ while (isspace(*desc)) {
+ desc++; /* Skip leading blanks. */
+ }
+ /* Is the font already in the cache? */
+ hPtr = Blt_FindHashEntry(&fontTable, desc);
+ if (hPtr != NULL) {
+ FtFont *ftPtr;
+
+ ftPtr = Tcl_GetHashValue(hPtr);
+ ftPtr->refCount++;
+ return ftPtr;
+ } else {
+ XftFont *xftPtr;
+
+ xftPtr = FtOpenFont(interp, tkwin, objPtr);
+ if (xftPtr != NULL) {
+ return FtNewFont(interp, tkwin, desc, xftPtr);
+ }
+ }
+ return NULL;
+}
+
+const char *
+Blt_GetFontFileFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *sizePtr)
+{
+ Tk_Window tkwin;
+ FcResult result;
+ FcChar8 *fileName;
+ FcPattern *pattern;
+ double size;
+
+ tkwin = Tk_MainWindow(interp);
+ if (!alias_initialized) {
+ MakeAliasTable(tkwin);
+ alias_initialized++;
+ }
+ if (!IsXRenderAvailable(tkwin)) {
+ Tcl_AppendResult(interp, "can't open Xft font: ",
+ "X server doesn't support XRENDER extension",
+ (char *)NULL);
+ return NULL;
+ }
+ pattern = FtGetFontPattern(interp, tkwin, objPtr);
+ if (pattern == NULL) {
+ return NULL;
+ }
+ result = FcPatternGetDouble(pattern, FC_SIZE, 0, &size);
+ if (result != FcResultMatch) {
+ size = 12.0;
+ }
+ result = FcPatternGetString(pattern, FC_FILE, 0, &fileName);
+ FcPatternDestroy(pattern);
+ if (result != FcResultMatch) {
+ return NULL;
+ }
+ *sizePtr = size;
+ return (const char *)fileName;
+}
+
+const char *
+Blt_GetFontFile(Tcl_Interp *interp, const char *fontName, double *sizePtr)
+{
+ Tcl_Obj *objPtr;
+ const char *fileName;
+
+ objPtr = Tcl_NewStringObj(fontName, strlen(fontName));
+ Tcl_IncrRefCount(objPtr);
+ fileName = Blt_GetFontFileFromObj(interp, objPtr, sizePtr);
+ Tcl_DecrRefCount(objPtr);
+ return fileName;
+}
+
+
+static const char *
+FtNameOfFontProc(_Blt_Font *fontPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+ return ftPtr->name;
+}
+
+static const char *
+FtFamilyOfFontProc(_Blt_Font *fontPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+ FcChar8 *string;
+ FcResult result;
+
+ result = FcPatternGetString(ftPtr->pattern, FC_FAMILY, 0, &string);
+ if (result == FcResultMatch) {
+ return (const char *)string;
+ }
+ return NULL;
+}
+
+
+static Font
+FtFontIdProc(_Blt_Font *fontPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+ return ftPtr->fid;
+}
+
+static void
+FtGetFontMetricsProc(_Blt_Font *fontPtr, Blt_FontMetrics *mPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+ Blt_HashEntry *hPtr;
+
+ /* Always take font metrics from the non-rotated font. */
+ hPtr = Blt_FindHashEntry(&ftPtr->fontTable, (char *)0L);
+ if (hPtr != NULL) {
+ FT_UInt glyph;
+ XGlyphInfo metrics;
+ XftFont *xftPtr;
+
+ xftPtr = Blt_GetHashValue(hPtr);
+ glyph = XftCharIndex(ftPtr->display, xftPtr, '0');
+ XftGlyphExtents(ftPtr->display, xftPtr, &glyph, 1, &metrics);
+ mPtr->ascent = xftPtr->ascent;
+ mPtr->descent = xftPtr->descent;
+ mPtr->linespace = mPtr->ascent + mPtr->descent;
+ mPtr->tabWidth = ftPtr->tabWidth;
+ mPtr->underlinePos = ftPtr->underlinePos;
+ mPtr->underlineHeight = ftPtr->underlineHeight;
+ }
+}
+
+static int
+FtMeasureCharsProc(
+ _Blt_Font *fontPtr,
+ const char *source,
+ int nBytes,
+ int maxLength,
+ int flags,
+ int *lengthPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+
+ return FtMeasureChars(ftPtr, source, nBytes, maxLength, flags, lengthPtr);
+}
+
+static int
+FtTextStringWidthProc(Blt_Font font, const char *string, int nBytes)
+{
+ int width;
+
+ FtMeasureCharsProc(font, string, nBytes, -1, 0, &width);
+ return width;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FtPostscriptFontNameProc --
+ *
+ * Given a Xft font, return the name of the corresponding Postscript
+ * font.
+ *
+ * Results:
+ * The return value is the pointsize of the given Xft font. The name of
+ * the Postscript font is appended to dsPtr.
+ *
+ * Side effects:
+ * If the font does not exist on the printer, the print job will fail at
+ * print time. Given a "reasonable" Postscript printer, the following
+ * Tk_Font font families should print correctly:
+ *
+ * Avant Garde, Arial, Bookman, Courier, Courier New, Geneva,
+ * Helvetica, Monaco, New Century Schoolbook, New York, Palatino,
+ * Symbol, Times, Times New Roman, Zapf Chancery, and Zapf Dingbats.
+ *
+ * Any other Xft font families may not print correctly because the
+ * computed Postscript font name may be incorrect.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+FtPostscriptFontNameProc(_Blt_Font *fontPtr, Tcl_DString *resultPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+ FcChar8 *string;
+ const char *family;
+ FcResult result;
+ int weight, slant;
+ double size;
+ int flags;
+
+ result = FcPatternGetString(ftPtr->pattern, FC_FAMILY, 0, &string);
+ family = (result == FcResultMatch) ? (const char *)string : "Unknown";
+ result = FcPatternGetInteger(ftPtr->pattern, FC_WEIGHT, 0, &weight);
+ if (result != FcResultMatch) {
+ weight = FC_WEIGHT_MEDIUM;
+ }
+ result = FcPatternGetInteger(ftPtr->pattern, FC_SLANT, 0, &slant);
+ if (result != FcResultMatch) {
+ slant = FC_SLANT_ROMAN;
+ }
+ flags = 0;
+ if (weight > FC_WEIGHT_MEDIUM) {
+ flags |= FONT_BOLD;
+ }
+ if (slant > FC_SLANT_ROMAN) {
+ flags |= FONT_ITALIC;
+ }
+ Blt_Ps_FontName(family, flags, resultPtr);
+ result = FcPatternGetDouble(ftPtr->pattern, FC_SIZE, 0, &size);
+ if (result != FcResultMatch) {
+ size = 12.0;
+ }
+ return (int)size;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FtUnderlineCharsProc --
+ *
+ * This procedure draws an underline for a given range of characters in a
+ * given string. It doesn't draw the characters (which are assumed to
+ * have been displayed previously); it just draws the underline. This
+ * procedure would mainly be used to quickly underline a few characters
+ * without having to construct an underlined font. To produce properly
+ * underlined text, the appropriate underlined font should be constructed
+ * and used.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Information gets displayed in "drawable".
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static void
+FtUnderlineCharsProc(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to
+ * draw. */
+ GC gc, /* Graphics context for actually
+ * drawing line. */
+ _Blt_Font *fontPtr,
+ const char *text, /* String containing characters to be
+ * underlined or overstruck. */
+ int textLen,
+ int x, int y, /* Coordinates at which first
+ * character of string is drawn. */
+ int first, /* Index of first byte of first
+ * character. */
+ int last, /* Index of first byte after the last
+ * character. */
+ int maxLength)
+{
+ int elWidth;
+ const char *s, *send;
+ FtFont *ftPtr = fontPtr->clientData;
+ int firstX, lastX, clipX;
+ int nBytes;
+ int accum, threshold, index, next;
+ int clipped;
+
+ /* Compute the width of an ellipsis and verify that we're not bigger
+ * than it. */
+ elWidth = Blt_TextWidth(fontPtr, "...", 3);
+ if (maxLength < 0) {
+ maxLength = threshold = 10000;
+ } else {
+ threshold = maxLength - elWidth;
+ }
+#if !HAVE_UTF
+ nBytes = 1;
+#endif /* !HAVE_UTF */
+ /* Compute the length of the string, stopping when we've surpassed our
+ * threshold. Also save the first and last coordinates of the substring to
+ * be underlined. */
+ clipX = lastX = -1, firstX = 0;
+ accum = next = 0;
+ clipped = FALSE;
+ for (index = 0, s = text, send = s + textLen; s < send;
+ s += nBytes, index++, accum += next) {
+#if HAVE_UTF
+ Tcl_UniChar ch;
+#endif /* HAVE_UTF */
+
+ if (index == first) {
+ firstX = accum;
+ }
+ if (index == last) {
+ lastX = accum;
+ break;
+ }
+#if HAVE_UTF
+ nBytes = Tcl_UtfToUniChar(s, &ch);
+#endif /* HAVE_UTF */
+ next = Blt_TextWidth(fontPtr, s, nBytes);
+ if ((next + accum) <= threshold) {
+ clipX = accum + next; /* Remember the last length where text
+ * plus the ellipsis fit */
+ }
+ if ((next + accum) > maxLength) {
+ clipped = TRUE;
+ break;
+ }
+ }
+ if (lastX < 0) {
+ lastX = accum;
+ }
+ if (clipped) {
+ if ((s < send) && (accum < elWidth)) {
+ return; /* Not enough room for "..." */
+ }
+ lastX = clipX + elWidth;
+ }
+ x += firstX;
+ y += ftPtr->underlinePos + 1;
+ XFillRectangle(display, drawable, gc, x, y, (unsigned int)(lastX - firstX),
+ (unsigned int)ftPtr->underlineHeight);
+}
+
+static int
+FtCanRotateFontProc(_Blt_Font *fontPtr, float angle)
+{
+ FcPattern *pattern;
+ FcResult result;
+ FtFont *ftPtr = fontPtr->clientData;
+ int boolean;
+ long angle10;
+
+ angle10 = (long)((double)angle * 10.0);
+ if (Blt_FindHashEntry(&ftPtr->fontTable, (char *)angle10) != NULL) {
+ return TRUE; /* Rotated font already exists. */
+ }
+
+ /*
+ * I don't know if this is correct. Some PCF fonts don't rotate properly.
+ * The chararcter positions are rotated but the glyph itself is drawn with
+ * no rotation. The standard Adobe Helvetica font is a good example of
+ * this. So I need to bail on those fonts. I check if scalable=True in
+ * the Xft font pattern to determine if the font will rotate properly.
+ */
+ result = FcPatternGetBool(ftPtr->pattern, FC_SCALABLE, 0, &boolean);
+ if ((result == FcResultMatch) && (!boolean)) {
+ return FALSE;
+ }
+ {
+ XftMatrix matrix;
+ double cosTheta, sinTheta, theta;
+
+ theta = ((double)angle / 180.0) * M_PI;
+ sinTheta = sin(theta);
+ cosTheta = cos(theta);
+
+ XftMatrixInit(&matrix);
+ XftMatrixRotate(&matrix, cosTheta, sinTheta);
+ pattern = FcPatternDuplicate(ftPtr->pattern);
+ FcPatternAddMatrix(pattern, FC_MATRIX, &matrix);
+ }
+
+ {
+ FcResult result;
+ FcPattern *match;
+
+ /*
+ * XftFontMatch only sets *result* on complete match failures. So
+ * initialize it here for a successful match. We'll accept partial
+ * matches.
+ */
+ result = FcResultMatch;
+ match = XftFontMatch(ftPtr->display, ftPtr->screenNum, pattern,&result);
+ if ((match != NULL) && (result == FcResultMatch)) {
+ XftFont *xftPtr;
+
+ xftPtr = XftFontOpenPattern(ftPtr->display, match);
+ /* Add the new rotated font to the hash table. */
+ if (xftPtr != NULL) {
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(&ftPtr->fontTable, (char *)angle10,
+ &isNew);
+ assert(isNew);
+ Blt_SetHashValue(hPtr, xftPtr);
+ FcPatternDestroy(pattern);
+ return TRUE;
+ }
+ }
+ FcPatternDestroy(pattern);
+ }
+ return FALSE;
+}
+
+static void
+FtDrawCharsProc(
+ Display *display, /* Display on which to draw. */
+ Drawable drawable, /* Window or pixmap in which to draw. */
+ GC gc, /* Graphics context for drawing
+ * characters. */
+ _Blt_Font *fontPtr, /* Font in which characters will be
+ * drawn; must be the same as font
+ * used in *GC. */
+ int depth,
+ float angle,
+ const char *source, /* UTF-8 string to be displayed. Need
+ * not be '\0' terminated. All Tk
+ * meta-characters (tabs, control
+ * characters, and newlines) should be
+ * stripped out of the string that is
+ * passed to this function. If they
+ * are not stripped out, they will be
+ * displayed as regular printing
+ * characters. */
+ int nBytes, /* # of bytes in string. */
+ int x, int y) /* Coordinates at which to place
+ * origin of string when drawing. */
+{
+ XftFont *xftPtr;
+ FtFont *ftPtr = fontPtr->clientData;
+ Blt_HashEntry *hPtr;
+ long angle10;
+
+ angle10 = (long)(angle * 10.0);
+ hPtr = Blt_FindHashEntry(&ftPtr->fontTable, (char *)angle10);
+ if (hPtr == NULL) {
+ fprintf(stderr, "can't find font %s rotated at %g degrees\n",
+ ftPtr->name, angle);
+ return; /* Can't find instance at requested angle. */
+ }
+ xftPtr = Blt_GetHashValue(hPtr);
+ if ((ftPtr->draw == 0) || (ftPtr->drawDepth != depth)) {
+ XftDraw *draw;
+
+ if (depth == 1) {
+ draw = XftDrawCreateBitmap(display, drawable);
+ } else {
+ draw = XftDrawCreate(display, drawable, ftPtr->visual,
+ ftPtr->colormap);
+ }
+ if (ftPtr->draw != 0) {
+ XftDrawDestroy(ftPtr->draw);
+ }
+ ftPtr->drawDepth = depth;
+ ftPtr->draw = draw;
+ ftPtr->drawable = drawable;
+ } else {
+ Tk_ErrorHandler handler;
+ handler = Tk_CreateErrorHandler(display, -1, -1, -1,
+ (Tk_ErrorProc *)NULL, (ClientData) NULL);
+ XftDrawChange(ftPtr->draw, drawable);
+ ftPtr->drawable = drawable;
+ Tk_DeleteErrorHandler(handler);
+ }
+ {
+ XGCValues values;
+
+ XGetGCValues(display, gc, GCForeground, &values);
+ if (values.foreground != ftPtr->color.pixel) {
+ XColor xc;
+
+ xc.pixel = values.foreground;
+ XQueryColor(display, ftPtr->colormap, &xc);
+ ftPtr->color.color.red = xc.red;
+ ftPtr->color.color.green = xc.green;
+ ftPtr->color.color.blue = xc.blue;
+ ftPtr->color.color.alpha = 0xffff; /* Assume opaque. */
+ ftPtr->color.pixel = values.foreground;
+ }
+ }
+
+ {
+#define NUM_SPEC 1024
+ XftGlyphFontSpec *specPtr;
+ XftGlyphFontSpec specs[NUM_SPEC+1];
+ int nSpecs;
+ const int maxCoord = 0x7FFF; /* Xft coordinates are 16 bit values */
+
+ nSpecs = 0;
+ specPtr = specs;
+ while ((nBytes > 0) && (x <= maxCoord) && (y <= maxCoord)) {
+ XftChar32 c;
+ int charLen;
+ XGlyphInfo metrics;
+
+ charLen = XftUtf8ToUcs4((XftChar8 *)source, &c, nBytes);
+ if (charLen <= 0) {
+ /* This should not happen, but it can. */
+ return;
+ }
+ source += charLen;
+ nBytes -= charLen;
+
+ specPtr = specs + nSpecs;
+ specPtr->font = xftPtr;
+ specPtr->glyph = XftCharIndex(display, xftPtr, c);
+ specPtr->x = x;
+ specPtr->y = y;
+ XftGlyphExtents(display, xftPtr, &specPtr->glyph, 1, &metrics);
+ x += metrics.xOff;
+ y += metrics.yOff;
+ nSpecs++, specPtr++;
+ if (nSpecs == NUM_SPEC) {
+ XftDrawGlyphFontSpec(ftPtr->draw, &ftPtr->color, specs, nSpecs);
+ nSpecs = 0;
+ specPtr = specs;
+ }
+ }
+ if (nSpecs > 0) {
+ XftDrawGlyphFontSpec(ftPtr->draw, &ftPtr->color, specs, nSpecs);
+ }
+ }
+}
+
+static void
+FtFreeFontProc(_Blt_Font *fontPtr)
+{
+ FtFont *ftPtr = fontPtr->clientData;
+
+ ftPtr->refCount--;
+ if (ftPtr->refCount <= 0) {
+ FtDeleteFont(ftPtr);
+ }
+ free(fontPtr);
+}
+
+#endif /* HAVE_LIBXFT */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetFontFromObj --
+ *
+ * Given a string description of a font, map the description to a
+ * corresponding Tk_Font that represents the font.
+ *
+ * Results:
+ * The return value is token for the font, or NULL if an error prevented
+ * the font from being created. If NULL is returned, an error message
+ * will be left in the interp's result.
+ *
+ * Side effects:
+ * The font is added to an internal database with a reference count. For
+ * each call to this procedure, there should eventually be a call to
+ * Tk_FreeFont() or Tk_FreeFontFromObj() so that the database is cleaned
+ * up when fonts aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_Font
+Blt_GetFontFromObj(
+ Tcl_Interp *interp, /* Interp for database and error
+ * return. */
+ Tk_Window tkwin, /* For display on which font will be
+ * used. */
+ Tcl_Obj *objPtr) /* String describing font, as: named
+ * font, native format, or parseable
+ * string. */
+{
+ _Blt_Font *fontPtr;
+
+ fontPtr = calloc(1, sizeof(_Blt_Font));
+ if (fontPtr == NULL) {
+ return NULL; /* Out of memory. */
+ }
+ if (!alias_initialized) {
+ MakeAliasTable(tkwin);
+ alias_initialized++;
+ }
+#ifdef HAVE_LIBXFT
+ if (IsXRenderAvailable(tkwin)) {
+ FtFont *ftPtr;
+
+ /* Check first if we open the specified font as an XFT font. */
+ ftPtr = FtGetFontFromObj(interp, tkwin, objPtr);
+ if (ftPtr != NULL) {
+ fontPtr->classPtr = &ftFontClass;
+ fontPtr->clientData = ftPtr;
+ fontPtr->interp = interp;
+ fontPtr->display = Tk_Display(tkwin);
+ return fontPtr; /* Found Xft font. */
+ }
+ /* Otherwise fall thru and try to open font as a normal Tk font. */
+ }
+#endif /* HAVE_LIBXFT */
+ fontPtr->clientData = TkGetFontFromObj(interp, tkwin, objPtr);
+ if (fontPtr->clientData == NULL) {
+ free(fontPtr);
+ return NULL; /* Failed to find either Xft or Tk
+ * fonts. */
+ }
+ fontPtr->classPtr = &tkFontClass;
+ fontPtr->interp = interp;
+ fontPtr->display = Tk_Display(tkwin);
+ return fontPtr; /* Found Tk font. */
+}
+
+
+Blt_Font
+Blt_AllocFontFromObj(
+ Tcl_Interp *interp, /* Interp for database and error return. */
+ Tk_Window tkwin, /* For screen on which font will be used. */
+ Tcl_Obj *objPtr) /* Object describing font, as: named font,
+ * native format, or parseable string. */
+{
+ return Blt_GetFontFromObj(interp, tkwin, objPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetFont --
+ *
+ * Given a string description of a font, map the description to a
+ * corresponding Tk_Font that represents the font.
+ *
+ * Results:
+ * The return value is token for the font, or NULL if an error prevented
+ * the font from being created. If NULL is returned, an error message
+ * will be left in interp's result object.
+ *
+ * Side effects:
+ * The font is added to an internal database with a reference count. For
+ * each call to this procedure, there should eventually be a call to
+ * Blt_FreeFont so that the database is cleaned up when fonts aren't in
+ * use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Blt_Font
+Blt_GetFont(
+ Tcl_Interp *interp, /* Interp for database and error return. */
+ Tk_Window tkwin, /* For screen on which font will be used. */
+ const char *string) /* Object describing font, as: named font,
+ * native format, or parseable string. */
+{
+ Blt_Font font;
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewStringObj(string, strlen(string));
+ Tcl_IncrRefCount(objPtr);
+ font = Blt_GetFontFromObj(interp, tkwin, objPtr);
+ Tcl_DecrRefCount(objPtr);
+ return font;
+}
+
+Tcl_Interp *
+Blt_GetFontInterp(_Blt_Font *fontPtr)
+{
+ return fontPtr->interp;
+}
+
+int
+Blt_TextWidth(_Blt_Font *fontPtr, const char *string, int length)
+{
+ if (Blt_Ps_IsPrinting()) {
+ int width;
+
+ width = Blt_Ps_TextWidth(fontPtr, string, length);
+ if (width >= 0) {
+ return width;
+ }
+ }
+ return (*fontPtr->classPtr->textWidth)(fontPtr, string, length);
+}
+
+void
+Blt_GetFontMetrics(_Blt_Font *fontPtr, Blt_FontMetrics *fmPtr)
+{
+ if (Blt_Ps_IsPrinting()) {
+ if (Blt_Ps_GetFontMetrics(fontPtr, fmPtr) == TCL_OK) {
+ return;
+ }
+ }
+ return (*fontPtr->classPtr->getFontMetrics)(fontPtr, fmPtr);
+}
+
+
diff --git a/tlt3.0/bltUnixWindow.c b/tlt3.0/bltUnixWindow.c
new file mode 100644
index 0000000..88fb60f
--- /dev/null
+++ b/tlt3.0/bltUnixWindow.c
@@ -0,0 +1,211 @@
+
+/*
+ * bltUnixWindow.c --
+ *
+ * This module implements additional window functionality for the BLT
+ * toolkit, such as transparent Tk windows, and reparenting Tk
+ * windows.
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+
+#include <tkPort.h>
+#include <tkInt.h>
+
+#include "bltInt.h"
+
+Window
+Blt_GetParentWindow(Display *display, Window window)
+{
+ Window root, parent;
+ Window *dummy;
+ unsigned int count;
+
+ if (XQueryTree(display, window, &root, &parent, &dummy, &count) > 0) {
+ XFree(dummy);
+ return parent;
+ }
+ return None;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetWindowId --
+ *
+ * Returns the XID for the Tk_Window given. Starting in Tk 8.0,
+ * the toplevel widgets are wrapped by another window. Currently
+ * there's no way to get at that window, other than what is done
+ * here: query the X window hierarchy and retrieve the parent.
+ *
+ * Results:
+ * Returns the X Window ID of the widget. If it's a toplevel, then
+ * the XID of the wrapper is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+Window
+Blt_GetWindowId(Tk_Window tkwin)
+{
+ Window window;
+
+ Tk_MakeWindowExist(tkwin);
+ window = Tk_WindowId(tkwin);
+ if (Tk_IsTopLevel(tkwin)) {
+ Window parent;
+
+ parent = Blt_GetParentWindow(Tk_Display(tkwin), window);
+ if (parent != None) {
+ window = parent;
+ }
+ window = parent;
+ }
+ return window;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * XGeometryErrorProc --
+ *
+ * Flags errors generated from XGetGeometry calls to the X server.
+ *
+ * Results:
+ * Always returns 0.
+ *
+ * Side Effects:
+ * Sets a flag, indicating an error occurred.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+XGeometryErrorProc(ClientData clientData, XErrorEvent *errEventPtr)
+{
+ int *errorPtr = clientData;
+
+ *errorPtr = FALSE;
+ return 0;
+}
+
+int
+Blt_GetWindowRegion(Display *display, Window window, int *xPtr, int *yPtr,
+ int *widthPtr, int *heightPtr)
+{
+ Tk_ErrorHandler handler;
+ Window root;
+ int any = -1;
+ int result;
+ int x, y;
+ unsigned int w, h, bw, depth;
+
+ handler = Tk_CreateErrorHandler(display, any, X_GetGeometry, any,
+ XGeometryErrorProc, &result);
+ result = XGetGeometry(display, window, &root, &x, &y, &w, &h, &bw, &depth);
+ if (!result) {
+ goto error;
+ }
+ if (widthPtr != NULL) {
+ *widthPtr = (int)w;
+ }
+ if (heightPtr != NULL) {
+ *heightPtr = (int)h;
+ }
+ if ((xPtr != NULL) || (yPtr != NULL)) {
+ int rootX, rootY;
+ rootX = rootY = 0;
+
+ do {
+ Window *children, parent;
+ unsigned int n;
+
+ parent = -1;
+ result = XGetGeometry(display, window, &root, &x, &y, &w, &h,
+ &bw, &depth);
+ if (!result) {
+ goto error;
+ }
+ rootX += x + bw;
+ rootY += y + bw;
+ result = XQueryTree(display, window, &root, &parent, &children, &n);
+ XFree(children);
+ if (!result) {
+ goto error;
+ }
+ window = parent;
+ } while (window != root);
+
+ if (xPtr != NULL) {
+ *xPtr = rootX;
+ }
+ if (yPtr != NULL) {
+ *yPtr = rootY;
+ }
+ }
+ Tk_DeleteErrorHandler(handler);
+ XSync(display, False);
+ return TCL_OK;
+ error:
+ Tk_DeleteErrorHandler(handler);
+ XSync(display, False);
+ fprintf(stderr, "failed to get window region\n");
+ return TCL_ERROR;
+}
+
+int
+Blt_GetWindowFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Window *windowPtr)
+{
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ if (string[0] == '.') {
+ Tk_Window tkwin;
+
+ tkwin = Tk_NameToWindow(interp, string, Tk_MainWindow(interp));
+ if (tkwin == NULL) {
+ return TCL_ERROR;
+ }
+ if (Tk_WindowId(tkwin) == None) {
+ Tk_MakeWindowExist(tkwin);
+ }
+ *windowPtr = (Tk_IsTopLevel(tkwin)) ? Blt_GetWindowId(tkwin) :
+ Tk_WindowId(tkwin);
+ } else if (strcmp(string, "root") == 0) {
+ *windowPtr = Tk_RootWindow(Tk_MainWindow(interp));
+ } else {
+
+ int id;
+
+ if (Tcl_GetIntFromObj(interp, objPtr, &id) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *windowPtr = (Window)id;
+ }
+ return TCL_OK;
+}
+
diff --git a/tlt3.0/bltUtil.c b/tlt3.0/bltUtil.c
new file mode 100644
index 0000000..bdf4b42
--- /dev/null
+++ b/tlt3.0/bltUtil.c
@@ -0,0 +1,731 @@
+
+/*
+ * bltUtil.c --
+ *
+ * This module implements utility procedures for the BLT toolkit.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <stdarg.h>
+#include <float.h>
+#include <math.h>
+
+#include "bltInt.h"
+#include "bltOp.h"
+#include "bltHash.h"
+#include "bltDBuffer.h"
+
+char* Blt_Strdup(const char *string)
+{
+ size_t size;
+ char *ptr;
+
+ size = strlen(string) + 1;
+ ptr = malloc(size * sizeof(char));
+ if (ptr != NULL) {
+ strcpy(ptr, string);
+ }
+ return ptr;
+}
+
+void strtolower(char *s)
+{
+ while (*s != '\0') {
+ *s = tolower((unsigned char)(*s));
+ s++;
+ }
+}
+
+int TclGetLong(
+ Tcl_Interp *interp, /* Interpreter used for error reporting if not
+ * NULL. */
+ CONST char *src, /* String containing a (possibly signed) long
+ * integer in a form acceptable to
+ * Tcl_GetLongFromObj(). */
+ long *longPtr) /* Place to store converted long result. */
+{
+ Tcl_Obj obj;
+ int code;
+
+ obj.refCount = 1;
+ obj.bytes = (char *) src;
+ obj.length = strlen(src);
+ obj.typePtr = NULL;
+
+ code = Tcl_GetLongFromObj(interp, &obj, longPtr);
+ if (obj.refCount > 1) {
+ Tcl_Panic("invalid sharing of Tcl_Obj on C stack");
+ }
+ return code;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetDoubleFromString --
+ *
+ * Converts a string into a double precision number. This differs from
+ * Tcl's version in that it also allows NaN and +/-Inf. There are
+ * cases where NaNs are used to indicate holes in the data.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetDoubleFromString(Tcl_Interp *interp, const char *s, double *valuePtr)
+{
+ char *end;
+ double d;
+
+ errno = 0;
+ d = strtod(s, &end); /* INTL: Tcl source. */
+ if (end == s) {
+ badDouble:
+ if (interp != (Tcl_Interp *) NULL) {
+ Tcl_AppendResult(interp,
+ "expected floating-point number but got \"", s, "\"",
+ (char *) NULL);
+ }
+ return TCL_ERROR;
+ }
+ if (errno != 0 && (d == HUGE_VAL || d == -HUGE_VAL || d == 0)) {
+ if (interp != (Tcl_Interp *) NULL) {
+ char msg[64 + TCL_INTEGER_SPACE];
+
+ sprintf(msg, "unknown floating-point error, errno = %d", errno);
+ Tcl_AppendToObj(Tcl_GetObjResult(interp), msg, -1);
+ Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN", msg, (char *) NULL);
+ }
+ return TCL_ERROR;
+ }
+ while ((*end != 0) && isspace((unsigned char)(*end))) { /* INTL: ISO space. */
+ end++;
+ }
+ if (*end != 0) {
+ goto badDouble;
+ }
+ *valuePtr = d;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetDoubleFromObj --
+ *
+ * Converts a Tcl_Obj into a double precision number. This differs from
+ * Tcl's version in that it also allows NaN and +/-Inf. There are
+ * cases where NaNs are used to indicate holes in the data.
+ *
+ * Results:
+ * Returns a standard Tcl result.
+ *
+ * Side Effects:
+ * tclDoubleType is no longer available (in 8.5) as a global variable.
+ * We have to get a double obj and save its type pointer.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetDoubleFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, double *valuePtr)
+{
+ const char *string;
+ static Tcl_ObjType *tclDoubleTypePtr = NULL;
+
+ if (tclDoubleTypePtr == NULL) {
+ Tcl_Obj *objPtr;
+
+ objPtr = Tcl_NewDoubleObj(0.0);
+ tclDoubleTypePtr = (Tcl_ObjType*)(objPtr->typePtr);
+ Tcl_DecrRefCount(objPtr);
+ }
+ if (objPtr->typePtr == tclDoubleTypePtr) {
+ *valuePtr = objPtr->internalRep.doubleValue;
+ return TCL_OK;
+ }
+ string = Tcl_GetString(objPtr);
+ return Blt_GetDoubleFromString(interp, string, valuePtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CompareDictionary
+ *
+ * This function compares two strings as if they were being used in
+ * an index or card catalog. The case of alphabetic characters is
+ * ignored, except to break ties. Thus "B" comes before "b" but
+ * after "a". Also, integers embedded in the strings compare in
+ * numerical order. In other words, "x10y" comes after "x9y", not
+ * before it as it would when using strcmp().
+ *
+ * Results:
+ * A negative result means that the first element comes before the
+ * second, and a positive result means that the second element
+ * should come first. A result of zero means the two elements
+ * are equal and it doesn't matter which comes first.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+#if HAVE_UTF
+int
+Blt_DictionaryCompare(const char *left, const char *right)
+{
+ Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower;
+ int diff, zeros;
+ int secondaryDiff = 0;
+
+ for(;;) {
+ if ((isdigit((unsigned char)(*right))) && (isdigit((unsigned char)(*left)))) {
+ /*
+ * There are decimal numbers embedded in the two strings. Compare
+ * them as numbers, rather than strings. If one number has more
+ * leading zeros than the other, the number with more leading
+ * zeros sorts later, but only as a secondary choice.
+ */
+
+ zeros = 0;
+ while ((*right == '0') && (isdigit((unsigned char)(right[1])))) {
+ right++;
+ zeros--;
+ }
+ while ((*left == '0') && (isdigit((unsigned char)(left[1])))) {
+ left++;
+ zeros++;
+ }
+ if (secondaryDiff == 0) {
+ secondaryDiff = zeros;
+ }
+
+ /*
+ * The code below compares the numbers in the two strings without
+ * ever converting them to integers. It does this by first
+ * comparing the lengths of the numbers and then comparing the
+ * digit values.
+ */
+
+ diff = 0;
+ for (;;) {
+ if (diff == 0) {
+ diff = (unsigned char)(*left) - (unsigned char)(*right);
+ }
+ right++;
+ left++;
+
+ /* Ignore commas in numbers. */
+ if (*left == ',') {
+ left++;
+ }
+ if (*right == ',') {
+ right++;
+ }
+
+ if (!isdigit((unsigned char)(*right))) { /* INTL: digit */
+ if (isdigit((unsigned char)(*left))) { /* INTL: digit */
+ return 1;
+ } else {
+ /*
+ * The two numbers have the same length. See
+ * if their values are different.
+ */
+
+ if (diff != 0) {
+ return diff;
+ }
+ break;
+ }
+ } else if (!isdigit((unsigned char)(*left))) { /* INTL: digit */
+ return -1;
+ }
+ }
+ continue;
+ }
+
+ /*
+ * Convert character to Unicode for comparison purposes. If either
+ * string is at the terminating null, do a byte-wise comparison and
+ * bail out immediately.
+ */
+ if ((*left != '\0') && (*right != '\0')) {
+ left += Tcl_UtfToUniChar(left, &uniLeft);
+ right += Tcl_UtfToUniChar(right, &uniRight);
+ /*
+ * Convert both chars to lower for the comparison, because
+ * dictionary sorts are case insensitve. Convert to lower, not
+ * upper, so chars between Z and a will sort before A (where most
+ * other interesting punctuations occur)
+ */
+ uniLeftLower = Tcl_UniCharToLower(uniLeft);
+ uniRightLower = Tcl_UniCharToLower(uniRight);
+ } else {
+ diff = (unsigned char)(*left) - (unsigned char)(*right);
+ break;
+ }
+
+ diff = uniLeftLower - uniRightLower;
+ if (diff) {
+ return diff;
+ } else if (secondaryDiff == 0) {
+ if (Tcl_UniCharIsUpper(uniLeft) &&
+ Tcl_UniCharIsLower(uniRight)) {
+ secondaryDiff = -1;
+ } else if (Tcl_UniCharIsUpper(uniRight)
+ && Tcl_UniCharIsLower(uniLeft)) {
+ secondaryDiff = 1;
+ }
+ }
+ }
+ if (diff == 0) {
+ diff = secondaryDiff;
+ }
+ return diff;
+}
+
+#else
+
+int
+Blt_DictionaryCompare(const char *left, const char *right)
+{
+ int diff, zeros;
+ int secondaryDiff = 0;
+
+ while (1) {
+ if (isdigit((unsigned char)(*right)) && isdigit((unsigned char)(*left))) {
+ /*
+ * There are decimal numbers embedded in the two strings. Compare
+ * them as numbers, rather than strings. If one number has more
+ * leading zeros than the other, the number with more leading
+ * zeros sorts later, but only as a secondary choice.
+ */
+
+ zeros = 0;
+ while ((*right == '0') && (isdigit((unsigned char)(right[1])))) {
+ right++;
+ zeros--;
+ }
+ while ((*left == '0') && (isdigit((unsigned char)(left[1])))) {
+ left++;
+ zeros++;
+ }
+ if (secondaryDiff == 0) {
+ secondaryDiff = zeros;
+ }
+
+ /*
+ * The code below compares the numbers in the two strings without
+ * ever converting them to integers. It does this by first
+ * comparing the lengths of the numbers and then comparing the
+ * digit values.
+ */
+
+ diff = 0;
+ while (1) {
+ if (diff == 0) {
+ diff = (unsigned char)(*left) - (unsigned char)(*right);
+ }
+ right++;
+ left++;
+ /* Ignore commas in numbers. */
+ if (*left == ',') {
+ left++;
+ }
+ if (*right == ',') {
+ right++;
+ }
+ if (!isdigit((unsigned char)(*right))) {
+ if (isdigit((unsigned char)(*left))) {
+ return 1;
+ } else {
+ /*
+ * The two numbers have the same length. See
+ * if their values are different.
+ */
+
+ if (diff != 0) {
+ return diff;
+ }
+ break;
+ }
+ } else if (!isdigit((unsigned char)(*left))) {
+ return -1;
+ }
+ }
+ continue;
+ }
+ diff = (unsigned char)(*left) - (unsigned char)(*right);
+ if (diff) {
+ if (isupper((unsigned char)(*left)) && islower((unsigned char)(*right))) {
+ diff = (unsigned char)(tolower(*left)) - (unsigned char)(*right);
+ if (diff) {
+ return diff;
+ } else if (secondaryDiff == 0) {
+ secondaryDiff = -1;
+ }
+ } else if (isupper((unsigned char)(*right)) && islower((unsigned char)(*left))) {
+ diff = (unsigned char)(*left) - (unsigned char)(tolower((unsigned char)(*right)));
+ if (diff) {
+ return diff;
+ } else if (secondaryDiff == 0) {
+ secondaryDiff = 1;
+ }
+ } else {
+ return diff;
+ }
+ }
+ if (*left == 0) {
+ break;
+ }
+ left++;
+ right++;
+ }
+ if (diff == 0) {
+ diff = secondaryDiff;
+ }
+ return diff;
+}
+#endif
+
+/*ARGSUSED*/
+void
+Blt_Panic TCL_VARARGS_DEF(const char *, arg1)
+{
+ const char *format;
+ va_list args;
+
+ format = TCL_VARARGS_START(const char *, arg1, args);
+ vfprintf(stderr, format, args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ abort();
+}
+
+/*ARGSUSED*/
+int sprintf_s(char *s, size_t size, const char *fmt, /*args*/ ...)
+{
+ va_list ap;
+ int n;
+
+ va_start(ap, fmt);
+ n = vsnprintf(s, size, fmt, ap);
+ if ((n != (int)size) && (size > 0)) {
+ s[size-1] = '\0';
+ }
+ va_end(ap);
+ return n;
+}
+
+static char stringRep[200];
+
+const char *
+Blt_Itoa(int value)
+{
+ sprintf_s(stringRep, 200, "%d", value);
+ return stringRep;
+}
+
+const char *
+Blt_Ltoa(long value)
+{
+ sprintf_s(stringRep, 200, "%ld", value);
+ return stringRep;
+}
+
+const char *
+Blt_Utoa(unsigned int value)
+{
+ sprintf_s(stringRep, 200, "%u", value);
+ return stringRep;
+}
+
+const char *
+Blt_Dtoa(Tcl_Interp *interp, double value)
+{
+ Tcl_PrintDouble(interp, value, stringRep);
+ return stringRep;
+}
+
+int
+Blt_GlobalEvalObjv(Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+ int result;
+
+ for (i = 0; i < objc; i++) {
+ Tcl_IncrRefCount(objv[i]);
+ }
+ result = Tcl_EvalObjv(interp, objc, objv, TCL_EVAL_GLOBAL);
+ for (i = 0; i < objc; i++) {
+ Tcl_DecrRefCount(objv[i]);
+ }
+ return result;
+}
+
+int
+Blt_GetCountFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ int check, /* Can be COUNT_POS, COUNT_NNEG,
+ * or COUNT_ANY, */
+ long *valuePtr)
+{
+ long count;
+
+ if (Tcl_GetLongFromObj(interp, objPtr, &count) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ switch (check) {
+ case COUNT_NNEG:
+ if (count < 0) {
+ Tcl_AppendResult(interp, "bad value \"", Tcl_GetString(objPtr),
+ "\": can't be negative", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case COUNT_POS:
+ if (count <= 0) {
+ Tcl_AppendResult(interp, "bad value \"", Tcl_GetString(objPtr),
+ "\": must be positive", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+ case COUNT_ANY:
+ break;
+ }
+ *valuePtr = count;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BinaryOpSearch --
+ *
+ * Performs a binary search on the array of command operation
+ * specifications to find a partial, anchored match for the given
+ * operation string.
+ *
+ * Results:
+ * If the string matches unambiguously the index of the specification in
+ * the array is returned. If the string does not match, even as an
+ * abbreviation, any operation, -1 is returned. If the string matches,
+ * but ambiguously -2 is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+BinaryOpSearch(Blt_OpSpec *specs, int nSpecs, const char *string, int length)
+{
+ char c;
+ int high, low;
+
+ low = 0;
+ high = nSpecs - 1;
+ c = string[0];
+ while (low <= high) {
+ Blt_OpSpec *specPtr;
+ int compare;
+ int median;
+
+ median = (low + high) >> 1;
+ specPtr = specs + median;
+
+ /* Test the first character */
+ compare = c - specPtr->name[0];
+ if (compare == 0) {
+ /* Now test the entire string */
+ compare = strncmp(string, specPtr->name, length);
+ if (compare == 0) {
+ if ((int)length < specPtr->minChars) {
+ return -2; /* Ambiguous operation name */
+ }
+ }
+ }
+ if (compare < 0) {
+ high = median - 1;
+ } else if (compare > 0) {
+ low = median + 1;
+ } else {
+ return median; /* Op found. */
+ }
+ }
+ return -1; /* Can't find operation */
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LinearOpSearch --
+ *
+ * Performs a binary search on the array of command operation
+ * specifications to find a partial, anchored match for the given
+ * operation string.
+ *
+ * Results:
+ * If the string matches unambiguously the index of the specification in
+ * the array is returned. If the string does not match, even as an
+ * abbreviation, any operation, -1 is returned. If the string matches,
+ * but ambiguously -2 is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+LinearOpSearch(Blt_OpSpec *specs, int nSpecs, const char *string, int length)
+{
+ Blt_OpSpec *specPtr;
+ char c;
+ int nMatches, last;
+ int i;
+
+ c = string[0];
+ nMatches = 0;
+ last = -1;
+ for (specPtr = specs, i = 0; i < nSpecs; i++, specPtr++) {
+ if ((c == specPtr->name[0]) &&
+ (strncmp(string, specPtr->name, length) == 0)) {
+ last = i;
+ nMatches++;
+ if ((int)length == specPtr->minChars) {
+ break;
+ }
+ }
+ }
+ if (nMatches > 1) {
+ return -2; /* Ambiguous operation name */
+ }
+ if (nMatches == 0) {
+ return -1; /* Can't find operation */
+ }
+ return last; /* Op found. */
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetOpFromObj --
+ *
+ * Find the command operation given a string name. This is useful where
+ * a group of command operations have the same argument signature.
+ *
+ * Results:
+ * If found, a pointer to the procedure (function pointer) is returned.
+ * Otherwise NULL is returned and an error message containing a list of
+ * the possible commands is returned in interp->result.
+ *
+ *---------------------------------------------------------------------------
+ */
+void *
+Blt_GetOpFromObj(
+ Tcl_Interp *interp, /* Interpreter to report errors to */
+ int nSpecs, /* # of specifications in array */
+ Blt_OpSpec *specs, /* Op specification array */
+ int operPos, /* Position of operation in argument
+ * list. */
+ int objc, /* # of arguments in the argument *
+ * vector. This includes any
+ * prefixed arguments */
+ Tcl_Obj *const *objv, /* Argument vector */
+ int flags)
+{
+ Blt_OpSpec *specPtr;
+ const char *string;
+ int length;
+ int n;
+
+ if (objc <= operPos) { /* No operation argument */
+ Tcl_AppendResult(interp, "wrong # args: ", (char *)NULL);
+ usage:
+ Tcl_AppendResult(interp, "should be one of...", (char *)NULL);
+ for (n = 0; n < nSpecs; n++) {
+ int i;
+
+ Tcl_AppendResult(interp, "\n ", (char *)NULL);
+ for (i = 0; i < operPos; i++) {
+ Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
+ (char *)NULL);
+ }
+ specPtr = specs + n;
+ Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage,
+ (char *)NULL);
+ }
+ return NULL;
+ }
+ string = Tcl_GetStringFromObj(objv[operPos], &length);
+ if (flags & BLT_OP_LINEAR_SEARCH) {
+ n = LinearOpSearch(specs, nSpecs, string, length);
+ } else {
+ n = BinaryOpSearch(specs, nSpecs, string, length);
+ }
+ if (n == -2) {
+ char c;
+
+ Tcl_AppendResult(interp, "ambiguous", (char *)NULL);
+ if (operPos > 2) {
+ Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
+ (char *)NULL);
+ }
+ Tcl_AppendResult(interp, " operation \"", string, "\" matches: ",
+ (char *)NULL);
+
+ c = string[0];
+ for (n = 0; n < nSpecs; n++) {
+ specPtr = specs + n;
+ if ((c == specPtr->name[0]) &&
+ (strncmp(string, specPtr->name, length) == 0)) {
+ Tcl_AppendResult(interp, " ", specPtr->name, (char *)NULL);
+ }
+ }
+ return NULL;
+
+ } else if (n == -1) { /* Can't find operation, display help */
+ Tcl_AppendResult(interp, "bad", (char *)NULL);
+ if (operPos > 2) {
+ Tcl_AppendResult(interp, " ", Tcl_GetString(objv[operPos - 1]),
+ (char *)NULL);
+ }
+ Tcl_AppendResult(interp, " operation \"", string, "\": ", (char *)NULL);
+ goto usage;
+ }
+ specPtr = specs + n;
+ if ((objc < specPtr->minArgs) ||
+ ((specPtr->maxArgs > 0) && (objc > specPtr->maxArgs))) {
+ int i;
+
+ Tcl_AppendResult(interp, "wrong # args: should be \"", (char *)NULL);
+ for (i = 0; i < operPos; i++) {
+ Tcl_AppendResult(interp, Tcl_GetString(objv[i]), " ",
+ (char *)NULL);
+ }
+ Tcl_AppendResult(interp, specPtr->name, " ", specPtr->usage, "\"",
+ (char *)NULL);
+ return NULL;
+ }
+ return specPtr->proc;
+}
+
diff --git a/tlt3.0/bltVecCmd.c b/tlt3.0/bltVecCmd.c
new file mode 100644
index 0000000..2fd6beb
--- /dev/null
+++ b/tlt3.0/bltVecCmd.c
@@ -0,0 +1,2418 @@
+/*
+ * bltVecCmd.c --
+ *
+ * This module implements vector data objects.
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Code for binary data read operation was donated by Harold Kirsch.
+ *
+ */
+
+/*
+ * TODO:
+ * o Add H. Kirsch's vector binary read operation
+ * x binread file0
+ * x binread -file file0
+ *
+ * o Add ASCII/binary file reader
+ * x read fileName
+ *
+ * o Allow Tcl-based client notifications.
+ * vector x
+ * x notify call Display
+ * x notify delete Display
+ * x notify reorder #1 #2
+ */
+
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+
+#include "bltInt.h"
+#include "bltVecInt.h"
+#include "bltOp.h"
+#include "bltNsUtil.h"
+#include "bltSwitch.h"
+
+typedef int (VectorCmdProc)(Vector *vPtr, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv);
+
+static Blt_SwitchParseProc ObjToFFTVector;
+static Blt_SwitchCustom fftVectorSwitch = {
+ ObjToFFTVector, NULL, (ClientData)0,
+};
+
+static Blt_SwitchParseProc ObjToIndex;
+static Blt_SwitchCustom indexSwitch = {
+ ObjToIndex, NULL, (ClientData)0,
+};
+
+typedef struct {
+ Tcl_Obj *formatObjPtr;
+ int from, to;
+} PrintSwitches;
+
+static Blt_SwitchSpec printSwitches[] =
+{
+ {BLT_SWITCH_OBJ, "-format", "string",
+ Blt_Offset(PrintSwitches, formatObjPtr), 0},
+ {BLT_SWITCH_CUSTOM, "-from", "index",
+ Blt_Offset(PrintSwitches, from), 0, 0, &indexSwitch},
+ {BLT_SWITCH_CUSTOM, "-to", "index",
+ Blt_Offset(PrintSwitches, to), 0, 0, &indexSwitch},
+ {BLT_SWITCH_END}
+};
+
+
+typedef struct {
+ int flags;
+} SortSwitches;
+
+#define SORT_DECREASING (1<<0)
+#define SORT_UNIQUE (1<<1)
+
+static Blt_SwitchSpec sortSwitches[] =
+{
+ {BLT_SWITCH_BITMASK, "-decreasing", "",
+ Blt_Offset(SortSwitches, flags), 0, SORT_DECREASING},
+ {BLT_SWITCH_BITMASK, "-reverse", "",
+ Blt_Offset(SortSwitches, flags), 0, SORT_DECREASING},
+ {BLT_SWITCH_BITMASK, "-uniq", "",
+ Blt_Offset(SortSwitches, flags), 0, SORT_UNIQUE},
+ {BLT_SWITCH_END}
+};
+
+typedef struct {
+ double delta;
+ Vector *imagPtr; /* Vector containing imaginary part. */
+ Vector *freqPtr; /* Vector containing frequencies. */
+ VectorInterpData *dataPtr;
+ int mask; /* Flags controlling FFT. */
+} FFTData;
+
+
+static Blt_SwitchSpec fftSwitches[] = {
+ {BLT_SWITCH_CUSTOM, "-imagpart", "vector",
+ Blt_Offset(FFTData, imagPtr), 0, 0, &fftVectorSwitch},
+ {BLT_SWITCH_BITMASK, "-noconstant", "",
+ Blt_Offset(FFTData, mask), 0, FFT_NO_CONSTANT},
+ {BLT_SWITCH_BITMASK, "-spectrum", "",
+ Blt_Offset(FFTData, mask), 0, FFT_SPECTRUM},
+ {BLT_SWITCH_BITMASK, "-bartlett", "",
+ Blt_Offset(FFTData, mask), 0, FFT_BARTLETT},
+ {BLT_SWITCH_DOUBLE, "-delta", "float",
+ Blt_Offset(FFTData, mask), 0, 0, },
+ {BLT_SWITCH_CUSTOM, "-frequencies", "vector",
+ Blt_Offset(FFTData, freqPtr), 0, 0, &fftVectorSwitch},
+ {BLT_SWITCH_END}
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToFFTVector --
+ *
+ * Convert a string representing a vector into its vector structure.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToFFTVector(
+ ClientData clientData, /* Not used. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ const char *switchName, /* Not used. */
+ Tcl_Obj *objPtr, /* Name of vector. */
+ char *record, /* Structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ FFTData *dataPtr = (FFTData *)record;
+ Vector *vPtr;
+ Vector **vPtrPtr = (Vector **)(record + offset);
+ int isNew; /* Not used. */
+ char *string;
+
+ string = Tcl_GetString(objPtr);
+ vPtr = Blt_Vec_Create(dataPtr->dataPtr, string, string, string, &isNew);
+ if (vPtr == NULL) {
+ return TCL_ERROR;
+ }
+ *vPtrPtr = vPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ObjToIndex --
+ *
+ * Convert a string representing a vector into its vector structure.
+ *
+ * Results:
+ * The return value is a standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ObjToIndex(
+ ClientData clientData, /* Contains the vector in question to verify
+ * its length. */
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ const char *switchName, /* Not used. */
+ Tcl_Obj *objPtr, /* Name of vector. */
+ char *record, /* Structure record */
+ int offset, /* Offset to field in structure */
+ int flags) /* Not used. */
+{
+ Vector *vPtr = clientData;
+ int *indexPtr = (int *)(record + offset);
+ int index;
+
+ if (Blt_Vec_GetIndex(interp, vPtr, Tcl_GetString(objPtr), &index,
+ INDEX_CHECK, (Blt_VectorIndexProc **)NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *indexPtr = index;
+ return TCL_OK;
+
+}
+
+static Tcl_Obj *
+GetValues(Vector *vPtr, int first, int last)
+{
+ Tcl_Obj *listObjPtr;
+ double *vp, *vend;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (vp = vPtr->valueArr + first, vend = vPtr->valueArr + last; vp <= vend;
+ vp++) {
+ Tcl_ListObjAppendElement(vPtr->interp, listObjPtr,
+ Tcl_NewDoubleObj(*vp));
+ }
+ return listObjPtr;
+}
+
+static void
+ReplicateValue(Vector *vPtr, int first, int last, double value)
+{
+ double *vp, *vend;
+
+ for (vp = vPtr->valueArr + first, vend = vPtr->valueArr + last;
+ vp <= vend; vp++) {
+ *vp = value;
+ }
+ vPtr->notifyFlags |= UPDATE_RANGE;
+}
+
+static int
+CopyList(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+
+ if (Blt_Vec_SetLength(interp, vPtr, objc) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ double value;
+
+ if (Blt_ExprDoubleFromObj(interp, objv[i], &value) != TCL_OK) {
+ Blt_Vec_SetLength(interp, vPtr, i);
+ return TCL_ERROR;
+ }
+ vPtr->valueArr[i] = value;
+ }
+ return TCL_OK;
+}
+
+static int
+AppendVector(Vector *destPtr, Vector *srcPtr)
+{
+ size_t nBytes;
+ size_t oldSize, newSize;
+
+ oldSize = destPtr->length;
+ newSize = oldSize + srcPtr->last - srcPtr->first + 1;
+ if (Blt_Vec_ChangeLength(destPtr->interp, destPtr, newSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ nBytes = (newSize - oldSize) * sizeof(double);
+ memcpy((char *)(destPtr->valueArr + oldSize),
+ (srcPtr->valueArr + srcPtr->first), nBytes);
+ destPtr->notifyFlags |= UPDATE_RANGE;
+ return TCL_OK;
+}
+
+static int
+AppendList(Vector *vPtr, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Interp *interp = vPtr->interp;
+ int count;
+ int i;
+ double value;
+ int oldSize;
+
+ oldSize = vPtr->length;
+ if (Blt_Vec_ChangeLength(interp, vPtr, vPtr->length + objc) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ count = oldSize;
+ for (i = 0; i < objc; i++) {
+ if (Blt_ExprDoubleFromObj(interp, objv[i], &value) != TCL_OK) {
+ Blt_Vec_ChangeLength(interp, vPtr, count);
+ return TCL_ERROR;
+ }
+ vPtr->valueArr[count++] = value;
+ }
+ vPtr->notifyFlags |= UPDATE_RANGE;
+ return TCL_OK;
+}
+
+/* Vector instance option commands */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * AppendOp --
+ *
+ * Appends one of more TCL lists of values, or vector objects onto the
+ * end of the current vector object.
+ *
+ * Results:
+ * A standard TCL result. If a current vector can't be created,
+ * resized, any of the named vectors can't be found, or one of lists of
+ * values is invalid, TCL_ERROR is returned.
+ *
+ * Side Effects:
+ * Clients of current vector will be notified of the change.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+AppendOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+ int result;
+ Vector *v2Ptr;
+
+ for (i = 2; i < objc; i++) {
+ v2Ptr = Blt_Vec_ParseElement((Tcl_Interp *)NULL, vPtr->dataPtr,
+ Tcl_GetString(objv[i]), (const char **)NULL, NS_SEARCH_BOTH);
+ if (v2Ptr != NULL) {
+ result = AppendVector(vPtr, v2Ptr);
+ } else {
+ int nElem;
+ Tcl_Obj **elemObjArr;
+
+ if (Tcl_ListObjGetElements(interp, objv[i], &nElem, &elemObjArr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = AppendList(vPtr, nElem, elemObjArr);
+ }
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (objc > 2) {
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ClearOp --
+ *
+ * Deletes all the accumulated array indices for the TCL array associated
+ * will the vector. This routine can be used to free excess memory from
+ * a large vector.
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side Effects:
+ * Memory used for the entries of the TCL array variable is freed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ClearOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Blt_Vec_FlushCache(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteOp --
+ *
+ * Deletes the given indices from the vector. If no indices are provided
+ * the entire vector is deleted.
+ *
+ * Results:
+ * A standard TCL result. If any of the given indices is invalid,
+ * interp->result will an error message and TCL_ERROR is returned.
+ *
+ * Side Effects:
+ * The clients of the vector will be notified of the vector
+ * deletions.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+DeleteOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ unsigned char *unsetArr;
+ int i, j;
+ int count;
+ char *string;
+
+ /* FIXME: Don't delete vector with no indices. */
+ if (objc == 2) {
+ Blt_Vec_Free(vPtr);
+ return TCL_OK;
+ }
+
+ /* Allocate an "unset" bitmap the size of the vector. */
+ unsetArr = calloc(sizeof(unsigned char), (vPtr->length + 7) / 8);
+#define SetBit(i) \
+ unsetArr[(i) >> 3] |= (1 << ((i) & 0x07))
+#define GetBit(i) \
+ (unsetArr[(i) >> 3] & (1 << ((i) & 0x07)))
+
+ for (i = 2; i < objc; i++) {
+ string = Tcl_GetString(objv[i]);
+ if (Blt_Vec_GetIndexRange(interp, vPtr, string,
+ (INDEX_COLON | INDEX_CHECK), (Blt_VectorIndexProc **) NULL)
+ != TCL_OK) {
+ free(unsetArr);
+ return TCL_ERROR;
+ }
+ for (j = vPtr->first; j <= vPtr->last; j++) {
+ SetBit(j); /* Mark the range of elements for deletion. */
+ }
+ }
+ count = 0;
+ for (i = 0; i < vPtr->length; i++) {
+ if (GetBit(i)) {
+ continue; /* Skip elements marked for deletion. */
+ }
+ if (count < i) {
+ vPtr->valueArr[count] = vPtr->valueArr[i];
+ }
+ count++;
+ }
+ free(unsetArr);
+ vPtr->length = count;
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DupOp --
+ *
+ * Creates one or more duplicates of the vector object.
+ *
+ * Results:
+ * A standard TCL result. If a new vector can't be created,
+ * or and existing vector resized, TCL_ERROR is returned.
+ *
+ * Side Effects:
+ * Clients of existing vectors will be notified of the change.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+DupOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+
+ for (i = 2; i < objc; i++) {
+ Vector *v2Ptr;
+ char *name;
+ int isNew;
+
+ name = Tcl_GetString(objv[i]);
+ v2Ptr = Blt_Vec_Create(vPtr->dataPtr, name, name, name, &isNew);
+ if (v2Ptr == NULL) {
+ return TCL_ERROR;
+ }
+ if (v2Ptr == vPtr) {
+ continue;
+ }
+ if (Blt_Vec_Duplicate(v2Ptr, vPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (!isNew) {
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ }
+ }
+ return TCL_OK;
+}
+
+
+/* spinellia at acm.org START */
+
+/* fft implementation */
+/*ARGSUSED*/
+static int
+FFTOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Vector *v2Ptr = NULL;
+ int isNew;
+ FFTData data;
+ char *realVecName;
+
+ memset(&data, 0, sizeof(data));
+ data.delta = 1.0;
+
+ realVecName = Tcl_GetString(objv[2]);
+ v2Ptr = Blt_Vec_Create(vPtr->dataPtr, realVecName, realVecName,
+ realVecName, &isNew);
+ if (v2Ptr == NULL) {
+ return TCL_ERROR;
+ }
+ if (v2Ptr == vPtr) {
+ Tcl_AppendResult(interp, "real vector \"", realVecName, "\"",
+ " can't be the same as the source", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_ParseSwitches(interp, fftSwitches, objc - 3, objv + 3, &data,
+ BLT_SWITCH_DEFAULTS) < 0) {
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_FFT(interp, v2Ptr, data.imagPtr, data.freqPtr, data.delta,
+ data.mask, vPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* Update bookkeeping. */
+ if (!isNew) {
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ }
+ if (data.imagPtr != NULL) {
+ if (data.imagPtr->flush) {
+ Blt_Vec_FlushCache(data.imagPtr);
+ }
+ Blt_Vec_UpdateClients(data.imagPtr);
+ }
+ if (data.freqPtr != NULL) {
+ if (data.freqPtr->flush) {
+ Blt_Vec_FlushCache(data.freqPtr);
+ }
+ Blt_Vec_UpdateClients(data.freqPtr);
+ }
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+InverseFFTOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int isNew;
+ char *name;
+ Vector *srcImagPtr;
+ Vector *destRealPtr;
+ Vector *destImagPtr;
+
+ name = Tcl_GetString(objv[2]);
+ if (Blt_Vec_LookupName(vPtr->dataPtr, name, &srcImagPtr) != TCL_OK ) {
+ return TCL_ERROR;
+ }
+ name = Tcl_GetString(objv[3]);
+ destRealPtr = Blt_Vec_Create(vPtr->dataPtr, name, name, name, &isNew);
+ name = Tcl_GetString(objv[4]);
+ destImagPtr = Blt_Vec_Create(vPtr->dataPtr, name, name, name, &isNew);
+
+ if (Blt_Vec_InverseFFT(interp, srcImagPtr, destRealPtr, destImagPtr, vPtr)
+ != TCL_OK ){
+ return TCL_ERROR;
+ }
+ if (destRealPtr->flush) {
+ Blt_Vec_FlushCache(destRealPtr);
+ }
+ Blt_Vec_UpdateClients(destRealPtr);
+
+ if (destImagPtr->flush) {
+ Blt_Vec_FlushCache(destImagPtr);
+ }
+ Blt_Vec_UpdateClients(destImagPtr);
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * IndexOp --
+ *
+ * Sets or reads the value of the index. This simulates what the
+ * vector's variable does.
+ *
+ * Results:
+ * A standard TCL result. If the index is invalid,
+ * interp->result will an error message and TCL_ERROR is returned.
+ * Otherwise interp->result will contain the values.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+IndexOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int first, last;
+ char *string;
+
+ string = Tcl_GetString(objv[2]);
+ if (Blt_Vec_GetIndexRange(interp, vPtr, string, INDEX_ALL_FLAGS,
+ (Blt_VectorIndexProc **) NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ first = vPtr->first, last = vPtr->last;
+ if (objc == 3) {
+ Tcl_Obj *listObjPtr;
+
+ if (first == vPtr->length) {
+ Tcl_AppendResult(interp, "can't get index \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR; /* Can't read from index "++end" */
+ }
+ listObjPtr = GetValues(vPtr, first, last);
+ Tcl_SetObjResult(interp, listObjPtr);
+ } else {
+ double value;
+
+ /* FIXME: huh? Why set values here?. */
+ if (first == SPECIAL_INDEX) {
+ Tcl_AppendResult(interp, "can't set index \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR; /* Tried to set "min" or "max" */
+ }
+ if (Blt_ExprDoubleFromObj(interp, objv[3], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (first == vPtr->length) {
+ if (Blt_Vec_ChangeLength(interp, vPtr, vPtr->length + 1)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ ReplicateValue(vPtr, first, last, value);
+ Tcl_SetObjResult(interp, objv[3]);
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * LengthOp --
+ *
+ * Returns the length of the vector. If a new size is given, the
+ * vector is resized to the new vector.
+ *
+ * Results:
+ * A standard TCL result. If the new length is invalid,
+ * interp->result will an error message and TCL_ERROR is returned.
+ * Otherwise interp->result will contain the length of the vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+LengthOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ int nElem;
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &nElem) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (nElem < 0) {
+ Tcl_AppendResult(interp, "bad vector size \"",
+ Tcl_GetString(objv[2]), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if ((Blt_Vec_SetSize(interp, vPtr, nElem) != TCL_OK) ||
+ (Blt_Vec_SetLength(interp, vPtr, nElem) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), vPtr->length);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MapOp --
+ *
+ * Queries or sets the offset of the array index from the base
+ * address of the data array of values.
+ *
+ * Results:
+ * A standard TCL result. If the source vector doesn't exist
+ * or the source list is not a valid list of numbers, TCL_ERROR
+ * returned. Otherwise TCL_OK is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+MapOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ if (objc > 2) {
+ if (Blt_Vec_MapVariable(interp, vPtr, Tcl_GetString(objv[2]))
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (vPtr->arrayName != NULL) {
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), vPtr->arrayName, -1);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MaxOp --
+ *
+ * Returns the maximum value of the vector.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+MaxOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_SetDoubleObj(Tcl_GetObjResult(interp), Blt_Vec_Max(vPtr));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MergeOp --
+ *
+ * Merges the values from the given vectors to the current vector.
+ *
+ * Results:
+ * A standard TCL result. If any of the given vectors differ in size,
+ * TCL_ERROR is returned. Otherwise TCL_OK is returned and the
+ * vector data will contain merged values of the given vectors.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+MergeOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Vector **vecArr;
+ int refSize, nElem;
+ int i;
+ double *valuePtr, *valueArr;
+ Vector **vPtrPtr;
+
+ /* Allocate an array of vector pointers of each vector to be
+ * merged in the current vector. */
+ vecArr = malloc(sizeof(Vector *) * objc);
+ vPtrPtr = vecArr;
+
+ refSize = -1;
+ nElem = 0;
+ for (i = 2; i < objc; i++) {
+ Vector *v2Ptr;
+ int length;
+
+ if (Blt_Vec_LookupName(vPtr->dataPtr, Tcl_GetString(objv[i]), &v2Ptr)
+ != TCL_OK) {
+ free(vecArr);
+ return TCL_ERROR;
+ }
+ /* Check that all the vectors are the same length */
+ length = v2Ptr->last - v2Ptr->first + 1;
+ if (refSize < 0) {
+ refSize = length;
+ } else if (length != refSize) {
+ Tcl_AppendResult(vPtr->interp, "vectors \"", vPtr->name,
+ "\" and \"", v2Ptr->name, "\" differ in length",
+ (char *)NULL);
+ free(vecArr);
+ return TCL_ERROR;
+ }
+ *vPtrPtr++ = v2Ptr;
+ nElem += refSize;
+ }
+ *vPtrPtr = NULL;
+
+ valueArr = malloc(sizeof(double) * nElem);
+ if (valueArr == NULL) {
+ Tcl_AppendResult(vPtr->interp, "not enough memory to allocate ",
+ Blt_Itoa(nElem), " vector elements", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ /* Merge the values from each of the vectors into the current vector */
+ valuePtr = valueArr;
+ for (i = 0; i < refSize; i++) {
+ Vector **vpp;
+
+ for (vpp = vecArr; *vpp != NULL; vpp++) {
+ *valuePtr++ = (*vpp)->valueArr[i + (*vpp)->first];
+ }
+ }
+ free(vecArr);
+ Blt_Vec_Reset(vPtr, valueArr, nElem, nElem, TCL_DYNAMIC);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MinOp --
+ *
+ * Returns the minimum value of the vector.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+MinOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_SetDoubleObj(Tcl_GetObjResult(interp), Blt_Vec_Min(vPtr));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NormalizeOp --
+ *
+ * Normalizes the vector.
+ *
+ * Results:
+ * A standard TCL result. If the density is invalid, TCL_ERROR
+ * is returned. Otherwise TCL_OK is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+NormalizeOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+ double range;
+
+ Blt_Vec_UpdateRange(vPtr);
+ range = vPtr->max - vPtr->min;
+ if (objc > 2) {
+ Vector *v2Ptr;
+ int isNew;
+ char *string;
+
+ string = Tcl_GetString(objv[2]);
+ v2Ptr = Blt_Vec_Create(vPtr->dataPtr, string, string, string, &isNew);
+ if (v2Ptr == NULL) {
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_SetLength(interp, v2Ptr, vPtr->length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (i = 0; i < vPtr->length; i++) {
+ v2Ptr->valueArr[i] = (vPtr->valueArr[i] - vPtr->min) / range;
+ }
+ Blt_Vec_UpdateRange(v2Ptr);
+ if (!isNew) {
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ }
+ } else {
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (i = 0; i < vPtr->length; i++) {
+ double norm;
+
+ norm = (vPtr->valueArr[i] - vPtr->min) / range;
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(norm));
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NotifyOp --
+ *
+ * Notify clients of vector.
+ *
+ * Results:
+ * A standard TCL result. If any of the given vectors differ in size,
+ * TCL_ERROR is returned. Otherwise TCL_OK is returned and the
+ * vector data will contain merged values of the given vectors.
+ *
+ * x vector notify now
+ * x vector notify always
+ * x vector notify whenidle
+ * x vector notify update {}
+ * x vector notify delete {}
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+NotifyOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int option;
+ int bool;
+ enum optionIndices {
+ OPTION_ALWAYS, OPTION_NEVER, OPTION_WHENIDLE,
+ OPTION_NOW, OPTION_CANCEL, OPTION_PENDING
+ };
+ static const char *optionArr[] = {
+ "always", "never", "whenidle", "now", "cancel", "pending", NULL
+ };
+
+ if (Tcl_GetIndexFromObj(interp, objv[2], optionArr, "qualifier", TCL_EXACT,
+ &option) != TCL_OK) {
+ return TCL_OK;
+ }
+ switch (option) {
+ case OPTION_ALWAYS:
+ vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
+ vPtr->notifyFlags |= NOTIFY_ALWAYS;
+ break;
+ case OPTION_NEVER:
+ vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
+ vPtr->notifyFlags |= NOTIFY_NEVER;
+ break;
+ case OPTION_WHENIDLE:
+ vPtr->notifyFlags &= ~NOTIFY_WHEN_MASK;
+ vPtr->notifyFlags |= NOTIFY_WHENIDLE;
+ break;
+ case OPTION_NOW:
+ /* FIXME: How does this play when an update is pending? */
+ Blt_Vec_NotifyClients(vPtr);
+ break;
+ case OPTION_CANCEL:
+ if (vPtr->notifyFlags & NOTIFY_PENDING) {
+ vPtr->notifyFlags &= ~NOTIFY_PENDING;
+ Tcl_CancelIdleCall(Blt_Vec_NotifyClients, (ClientData)vPtr);
+ }
+ break;
+ case OPTION_PENDING:
+ bool = (vPtr->notifyFlags & NOTIFY_PENDING);
+ Tcl_SetBooleanObj(Tcl_GetObjResult(interp), bool);
+ break;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * PopulateOp --
+ *
+ * Creates or resizes a new vector based upon the density specified.
+ *
+ * Results:
+ * A standard TCL result. If the density is invalid, TCL_ERROR
+ * is returned. Otherwise TCL_OK is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+PopulateOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Vector *v2Ptr;
+ int size, density;
+ int isNew;
+ int i, j;
+ double *valuePtr;
+ int count;
+ char *string;
+
+ string = Tcl_GetString(objv[2]);
+ v2Ptr = Blt_Vec_Create(vPtr->dataPtr, string, string, string, &isNew);
+ if (v2Ptr == NULL) {
+ return TCL_ERROR;
+ }
+ if (vPtr->length == 0) {
+ return TCL_OK; /* Source vector is empty. */
+ }
+ if (Tcl_GetIntFromObj(interp, objv[3], &density) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (density < 1) {
+ Tcl_AppendResult(interp, "bad density \"", Tcl_GetString(objv[3]),
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ size = (vPtr->length - 1) * (density + 1) + 1;
+ if (Blt_Vec_SetLength(interp, v2Ptr, size) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ count = 0;
+ valuePtr = v2Ptr->valueArr;
+ for (i = 0; i < (vPtr->length - 1); i++) {
+ double slice, range;
+
+ range = vPtr->valueArr[i + 1] - vPtr->valueArr[i];
+ slice = range / (double)(density + 1);
+ for (j = 0; j <= density; j++) {
+ *valuePtr = vPtr->valueArr[i] + (slice * (double)j);
+ valuePtr++;
+ count++;
+ }
+ }
+ count++;
+ *valuePtr = vPtr->valueArr[i];
+ assert(count == v2Ptr->length);
+ if (!isNew) {
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ValuesOp --
+ *
+ * Print the values vector.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ValuesOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ PrintSwitches switches;
+
+ switches.formatObjPtr = NULL;
+ switches.from = 0;
+ switches.to = vPtr->length - 1;
+ indexSwitch.clientData = vPtr;
+ if (Blt_ParseSwitches(interp, printSwitches, objc - 2, objv + 2, &switches,
+ BLT_SWITCH_DEFAULTS) < 0) {
+ return TCL_ERROR;
+ }
+ if (switches.from > switches.to) {
+ int tmp;
+ /* swap positions. */
+ tmp = switches.to;
+ switches.to = switches.from;
+ switches.from = tmp;
+ }
+ if (switches.formatObjPtr == NULL) {
+ Tcl_Obj *listObjPtr;
+ int i;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (i = switches.from; i <= switches.to; i++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(vPtr->valueArr[i]));
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ } else {
+ Tcl_DString ds;
+ char buffer[200];
+ const char *fmt;
+ int i;
+
+ Tcl_DStringInit(&ds);
+ fmt = Tcl_GetString(switches.formatObjPtr);
+ for (i = switches.from; i <= switches.to; i++) {
+ sprintf(buffer, fmt, vPtr->valueArr[i]);
+ Tcl_DStringAppend(&ds, buffer, -1);
+ }
+ Tcl_DStringResult(interp, &ds);
+ Tcl_DStringFree(&ds);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RangeOp --
+ *
+ * Returns a TCL list of the range of vector values specified.
+ *
+ * Results:
+ * A standard TCL result. If the given range is invalid, TCL_ERROR
+ * is returned. Otherwise TCL_OK is returned and interp->result
+ * will contain the list of values.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+RangeOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Obj *listObjPtr;
+ int first, last;
+ int i;
+
+ if (objc == 2) {
+ first = 0;
+ last = vPtr->length - 1;
+ } else if (objc == 4) {
+ if ((Blt_Vec_GetIndex(interp, vPtr, Tcl_GetString(objv[2]), &first,
+ INDEX_CHECK, (Blt_VectorIndexProc **) NULL) != TCL_OK) ||
+ (Blt_Vec_GetIndex(interp, vPtr, Tcl_GetString(objv[3]), &last,
+ INDEX_CHECK, (Blt_VectorIndexProc **) NULL) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetString(objv[0]), " range ?first last?", (char *)NULL);
+ return TCL_ERROR;
+ }
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (first > last) {
+ /* Return the list reversed */
+ for (i = last; i <= first; i++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(vPtr->valueArr[i]));
+ }
+ } else {
+ for (i = first; i <= last; i++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(vPtr->valueArr[i]));
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InRange --
+ *
+ * Determines if a value lies within a given range.
+ *
+ * The value is normalized and compared against the interval
+ * [0..1], where 0.0 is the minimum and 1.0 is the maximum.
+ * DBL_EPSILON is the smallest number that can be represented
+ * on the host machine, such that (1.0 + epsilon) != 1.0.
+ *
+ * Please note, min cannot be greater than max.
+ *
+ * Results:
+ * If the value is within of the interval [min..max], 1 is
+ * returned; 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+INLINE static int
+InRange(double value, double min, double max)
+{
+ double range;
+
+ range = max - min;
+ if (range < DBL_EPSILON) {
+ return (fabs(max - value) < DBL_EPSILON);
+ } else {
+ double norm;
+
+ norm = (value - min) / range;
+ return ((norm >= -DBL_EPSILON) && ((norm - 1.0) < DBL_EPSILON));
+ }
+}
+
+enum NativeFormats {
+ FMT_UNKNOWN = -1,
+ FMT_UCHAR, FMT_CHAR,
+ FMT_USHORT, FMT_SHORT,
+ FMT_UINT, FMT_INT,
+ FMT_ULONG, FMT_LONG,
+ FMT_FLOAT, FMT_DOUBLE
+};
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetBinaryFormat
+ *
+ * Translates a format string into a native type. Valid formats are
+ *
+ * signed i1, i2, i4, i8
+ * unsigned u1, u2, u4, u8
+ * real r4, r8, r16
+ *
+ * There must be a corresponding native type. For example, this for
+ * reading 2-byte binary integers from an instrument and converting them
+ * to unsigned shorts or ints.
+ *
+ *---------------------------------------------------------------------------
+ */
+static enum NativeFormats
+GetBinaryFormat(Tcl_Interp *interp, char *string, int *sizePtr)
+{
+ char c;
+
+ c = tolower(string[0]);
+ if (Tcl_GetInt(interp, string + 1, sizePtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "unknown binary format \"", string,
+ "\": incorrect byte size", (char *)NULL);
+ return FMT_UNKNOWN;
+ }
+ switch (c) {
+ case 'r':
+ if (*sizePtr == sizeof(double)) {
+ return FMT_DOUBLE;
+ } else if (*sizePtr == sizeof(float)) {
+ return FMT_FLOAT;
+ }
+ break;
+
+ case 'i':
+ if (*sizePtr == sizeof(char)) {
+ return FMT_CHAR;
+ } else if (*sizePtr == sizeof(int)) {
+ return FMT_INT;
+ } else if (*sizePtr == sizeof(long)) {
+ return FMT_LONG;
+ } else if (*sizePtr == sizeof(short)) {
+ return FMT_SHORT;
+ }
+ break;
+
+ case 'u':
+ if (*sizePtr == sizeof(unsigned char)) {
+ return FMT_UCHAR;
+ } else if (*sizePtr == sizeof(unsigned int)) {
+ return FMT_UINT;
+ } else if (*sizePtr == sizeof(unsigned long)) {
+ return FMT_ULONG;
+ } else if (*sizePtr == sizeof(unsigned short)) {
+ return FMT_USHORT;
+ }
+ break;
+
+ default:
+ Tcl_AppendResult(interp, "unknown binary format \"", string,
+ "\": should be either i#, r#, u# (where # is size in bytes)",
+ (char *)NULL);
+ return FMT_UNKNOWN;
+ }
+ Tcl_AppendResult(interp, "can't handle format \"", string, "\"",
+ (char *)NULL);
+ return FMT_UNKNOWN;
+}
+
+static int
+CopyValues(Vector *vPtr, char *byteArr, enum NativeFormats fmt, int size,
+ int length, int swap, int *indexPtr)
+{
+ int i, n;
+ int newSize;
+
+ if ((swap) && (size > 1)) {
+ int nBytes = size * length;
+ unsigned char *p;
+ int left, right;
+
+ for (i = 0; i < nBytes; i += size) {
+ p = (unsigned char *)(byteArr + i);
+ for (left = 0, right = size - 1; left < right; left++, right--) {
+ p[left] ^= p[right];
+ p[right] ^= p[left];
+ p[left] ^= p[right];
+ }
+
+ }
+ }
+ newSize = *indexPtr + length;
+ if (newSize > vPtr->length) {
+ if (Blt_Vec_ChangeLength(vPtr->interp, vPtr, newSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+#define CopyArrayToVector(vPtr, arr) \
+ for (i = 0, n = *indexPtr; i < length; i++, n++) { \
+ (vPtr)->valueArr[n] = (double)(arr)[i]; \
+ }
+
+ switch (fmt) {
+ case FMT_CHAR:
+ CopyArrayToVector(vPtr, (char *)byteArr);
+ break;
+
+ case FMT_UCHAR:
+ CopyArrayToVector(vPtr, (unsigned char *)byteArr);
+ break;
+
+ case FMT_INT:
+ CopyArrayToVector(vPtr, (int *)byteArr);
+ break;
+
+ case FMT_UINT:
+ CopyArrayToVector(vPtr, (unsigned int *)byteArr);
+ break;
+
+ case FMT_LONG:
+ CopyArrayToVector(vPtr, (long *)byteArr);
+ break;
+
+ case FMT_ULONG:
+ CopyArrayToVector(vPtr, (unsigned long *)byteArr);
+ break;
+
+ case FMT_SHORT:
+ CopyArrayToVector(vPtr, (short int *)byteArr);
+ break;
+
+ case FMT_USHORT:
+ CopyArrayToVector(vPtr, (unsigned short int *)byteArr);
+ break;
+
+ case FMT_FLOAT:
+ CopyArrayToVector(vPtr, (float *)byteArr);
+ break;
+
+ case FMT_DOUBLE:
+ CopyArrayToVector(vPtr, (double *)byteArr);
+ break;
+
+ case FMT_UNKNOWN:
+ break;
+ }
+ *indexPtr += length;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * BinreadOp --
+ *
+ * Reads binary values from a TCL channel. Values are either appended to
+ * the end of the vector or placed at a given index (using the "-at"
+ * option), overwriting existing values. Data is read until EOF is found
+ * on the channel or a specified number of values are read. (note that
+ * this is not necessarily the same as the number of bytes).
+ *
+ * The following flags are supported:
+ * -swap Swap bytes
+ * -at index Start writing data at the index.
+ * -format fmt Specifies the format of the data.
+ *
+ * This binary reader was created and graciously donated by Harald Kirsch
+ * (kir at iitb.fhg.de). Anything that's wrong is due to my (gah) munging
+ * of the code.
+ *
+ * Results:
+ * Returns a standard TCL result. The interpreter result will contain the
+ * number of values (not the number of bytes) read.
+ *
+ * Caveats:
+ * Channel reads must end on an element boundary.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+BinreadOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Tcl_Channel channel;
+ char *byteArr;
+ char *string;
+ enum NativeFormats fmt;
+ int arraySize, bytesRead;
+ int count, total;
+ int first;
+ int size, length, mode;
+ int swap;
+ int i;
+
+ string = Tcl_GetString(objv[2]);
+ channel = Tcl_GetChannel(interp, string, &mode);
+ if (channel == NULL) {
+ return TCL_ERROR;
+ }
+ if ((mode & TCL_READABLE) == 0) {
+ Tcl_AppendResult(interp, "channel \"", string,
+ "\" wasn't opened for reading", (char *)NULL);
+ return TCL_ERROR;
+ }
+ first = vPtr->length;
+ fmt = FMT_DOUBLE;
+ size = sizeof(double);
+ swap = FALSE;
+ count = 0;
+
+ if (objc > 3) {
+ string = Tcl_GetString(objv[3]);
+ if (string[0] != '-') {
+ long int value;
+ /* Get the number of values to read. */
+ if (Tcl_GetLongFromObj(interp, objv[3], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (value < 0) {
+ Tcl_AppendResult(interp, "count can't be negative",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ count = (size_t)value;
+ objc--, objv++;
+ }
+ }
+ /* Process any option-value pairs that remain. */
+ for (i = 3; i < objc; i++) {
+ string = Tcl_GetString(objv[i]);
+ if (strcmp(string, "-swap") == 0) {
+ swap = TRUE;
+ } else if (strcmp(string, "-format") == 0) {
+ i++;
+ if (i >= objc) {
+ Tcl_AppendResult(interp, "missing arg after \"", string,
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[i]);
+ fmt = GetBinaryFormat(interp, string, &size);
+ if (fmt == FMT_UNKNOWN) {
+ return TCL_ERROR;
+ }
+ } else if (strcmp(string, "-at") == 0) {
+ i++;
+ if (i >= objc) {
+ Tcl_AppendResult(interp, "missing arg after \"", string,
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[i]);
+ if (Blt_Vec_GetIndex(interp, vPtr, string, &first, 0,
+ (Blt_VectorIndexProc **)NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (first > vPtr->length) {
+ Tcl_AppendResult(interp, "index \"", string,
+ "\" is out of range", (char *)NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+#define BUFFER_SIZE 1024
+ if (count == 0) {
+ arraySize = BUFFER_SIZE * size;
+ } else {
+ arraySize = count * size;
+ }
+
+ byteArr = malloc(arraySize);
+ /* FIXME: restore old channel translation later? */
+ if (Tcl_SetChannelOption(interp, channel, "-translation",
+ "binary") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ total = 0;
+ while (!Tcl_Eof(channel)) {
+ bytesRead = Tcl_Read(channel, byteArr, arraySize);
+ if (bytesRead < 0) {
+ Tcl_AppendResult(interp, "error reading channel: ",
+ Tcl_PosixError(interp), (char *)NULL);
+ return TCL_ERROR;
+ }
+ if ((bytesRead % size) != 0) {
+ Tcl_AppendResult(interp, "error reading channel: short read",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ length = bytesRead / size;
+ if (CopyValues(vPtr, byteArr, fmt, size, length, swap, &first)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ total += length;
+ if (count > 0) {
+ break;
+ }
+ }
+ free(byteArr);
+
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+
+ /* Set the result as the number of values read. */
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), total);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SearchOp --
+ *
+ * Searches for a value in the vector. Returns the indices of all vector
+ * elements matching a particular value.
+ *
+ * Results:
+ * Always returns TCL_OK. interp->result will contain a list of the
+ * indices of array elements matching value. If no elements match,
+ * interp->result will contain the empty string.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SearchOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ double min, max;
+ int i;
+ int wantValue;
+ char *string;
+ Tcl_Obj *listObjPtr;
+
+ wantValue = FALSE;
+ string = Tcl_GetString(objv[2]);
+ if ((string[0] == '-') && (strcmp(string, "-value") == 0)) {
+ wantValue = TRUE;
+ objv++, objc--;
+ }
+ if (Blt_ExprDoubleFromObj(interp, objv[2], &min) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ max = min;
+ if (objc > 4) {
+ Tcl_AppendResult(interp, "wrong # arguments: should be \"",
+ Tcl_GetString(objv[0]), " search ?-value? min ?max?",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if ((objc > 3) &&
+ (Blt_ExprDoubleFromObj(interp, objv[3], &max) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if ((min - max) >= DBL_EPSILON) {
+ return TCL_OK; /* Bogus range. Don't bother looking. */
+ }
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (wantValue) {
+ for (i = 0; i < vPtr->length; i++) {
+ if (InRange(vPtr->valueArr[i], min, max)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(vPtr->valueArr[i]));
+ }
+ }
+ } else {
+ for (i = 0; i < vPtr->length; i++) {
+ if (InRange(vPtr->valueArr[i], min, max)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewIntObj(i + vPtr->offset));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * OffsetOp --
+ *
+ * Queries or sets the offset of the array index from the base address of
+ * the data array of values.
+ *
+ * Results:
+ * A standard TCL result. If the source vector doesn't exist or the
+ * source list is not a valid list of numbers, TCL_ERROR returned.
+ * Otherwise TCL_OK is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+OffsetOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ if (objc == 3) {
+ int newOffset;
+
+ if (Tcl_GetIntFromObj(interp, objv[2], &newOffset) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vPtr->offset = newOffset;
+ }
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), vPtr->offset);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * RandomOp --
+ *
+ * Generates random values for the length of the vector.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+RandomOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int i;
+
+ for (i = 0; i < vPtr->length; i++) {
+ vPtr->valueArr[i] = drand48();
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SeqOp --
+ *
+ * Generates a sequence of values in the vector.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SeqOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int n;
+ double start, stop;
+
+ if (Blt_ExprDoubleFromObj(interp, objv[2], &start) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Blt_ExprDoubleFromObj(interp, objv[3], &stop) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ n = vPtr->length;
+ if ((objc > 4) && (Blt_ExprIntFromObj(interp, objv[4], &n) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ if (n > 1) {
+ int i;
+ double step;
+
+ if (Blt_Vec_SetLength(interp, vPtr, n) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ step = (stop - start) / (double)(n - 1);
+ for (i = 0; i < n; i++) {
+ vPtr->valueArr[i] = start + (step * i);
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SetOp --
+ *
+ * Sets the data of the vector object from a list of values.
+ *
+ * Results:
+ * A standard TCL result. If the source vector doesn't exist or the
+ * source list is not a valid list of numbers, TCL_ERROR returned.
+ * Otherwise TCL_OK is returned.
+ *
+ * Side Effects:
+ * The vector data is reset. Clients of the vector are notified. Any
+ * cached array indices are flushed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SetOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int result;
+ Vector *v2Ptr;
+ int nElem;
+ Tcl_Obj **elemObjArr;
+
+ /* The source can be either a list of numbers or another vector. */
+
+ v2Ptr = Blt_Vec_ParseElement((Tcl_Interp *)NULL, vPtr->dataPtr,
+ Tcl_GetString(objv[2]), NULL, NS_SEARCH_BOTH);
+ if (v2Ptr != NULL) {
+ if (vPtr == v2Ptr) {
+ Vector *tmpPtr;
+ /*
+ * Source and destination vectors are the same. Copy the source
+ * first into a temporary vector to avoid memory overlaps.
+ */
+ tmpPtr = Blt_Vec_New(vPtr->dataPtr);
+ result = Blt_Vec_Duplicate(tmpPtr, v2Ptr);
+ if (result == TCL_OK) {
+ result = Blt_Vec_Duplicate(vPtr, tmpPtr);
+ }
+ Blt_Vec_Free(tmpPtr);
+ } else {
+ result = Blt_Vec_Duplicate(vPtr, v2Ptr);
+ }
+ } else if (Tcl_ListObjGetElements(interp, objv[2], &nElem, &elemObjArr)
+ == TCL_OK) {
+ result = CopyList(vPtr, interp, nElem, elemObjArr);
+ } else {
+ return TCL_ERROR;
+ }
+
+ if (result == TCL_OK) {
+ /*
+ * The vector has changed; so flush the array indices (they're wrong
+ * now), find the new range of the data, and notify the vector's
+ * clients that it's been modified.
+ */
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SimplifyOp --
+ *
+ * Sets the data of the vector object from a list of values.
+ *
+ * Results:
+ * A standard TCL result. If the source vector doesn't exist or the
+ * source list is not a valid list of numbers, TCL_ERROR returned.
+ * Otherwise TCL_OK is returned.
+ *
+ * Side Effects:
+ * The vector data is reset. Clients of the vector are notified. Any
+ * cached array indices are flushed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SimplifyOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ size_t i, n;
+ int length, nPoints;
+ int *simple;
+ double tolerance = 10.0;
+ Point2d *orig, *reduced;
+
+ length = vPtr->length;
+ nPoints = vPtr->length / 2;
+ simple = malloc(nPoints * sizeof(int));
+ reduced = malloc(nPoints * sizeof(Point2d));
+ orig = (Point2d *)vPtr->valueArr;
+ n = Blt_SimplifyLine(orig, 0, nPoints - 1, tolerance, simple);
+ for (i = 0; i < n; i++) {
+ reduced[i] = orig[simple[i]];
+ }
+ free(simple);
+ Blt_Vec_Reset(vPtr, (double *)reduced, n * 2, vPtr->length, TCL_DYNAMIC);
+ /*
+ * The vector has changed; so flush the array indices (they're wrong
+ * now), find the new range of the data, and notify the vector's
+ * clients that it's been modified.
+ */
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SplitOp --
+ *
+ * Copies the values from the vector evenly into one of more vectors.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+SplitOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ int nVectors;
+
+ nVectors = objc - 2;
+ if ((vPtr->length % nVectors) != 0) {
+ Tcl_AppendResult(interp, "can't split vector \"", vPtr->name,
+ "\" into ", Blt_Itoa(nVectors), " even parts.", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (nVectors > 0) {
+ Vector *v2Ptr;
+ char *string; /* Name of vector. */
+ int i, j, k;
+ int oldSize, newSize, extra, isNew;
+
+ extra = vPtr->length / nVectors;
+ for (i = 0; i < nVectors; i++) {
+ string = Tcl_GetString(objv[i+2]);
+ v2Ptr = Blt_Vec_Create(vPtr->dataPtr, string, string, string,
+ &isNew);
+ oldSize = v2Ptr->length;
+ newSize = oldSize + extra;
+ if (Blt_Vec_SetLength(interp, v2Ptr, newSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for (j = i, k = oldSize; j < vPtr->length; j += nVectors, k++) {
+ v2Ptr->valueArr[k] = vPtr->valueArr[j];
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+
+static Vector **sortVectors; /* Pointer to the array of values currently
+ * being sorted. */
+static int nSortVectors;
+static int sortDecreasing; /* Indicates the ordering of the sort. If
+ * non-zero, the vectors are sorted in
+ * decreasing order */
+
+static int
+CompareVectors(void *a, void *b)
+{
+ double delta;
+ int i;
+ int sign;
+ Vector *vPtr;
+
+ sign = (sortDecreasing) ? -1 : 1;
+ for (i = 0; i < nSortVectors; i++) {
+ vPtr = sortVectors[i];
+ delta = vPtr->valueArr[*(int *)a] - vPtr->valueArr[*(int *)b];
+ if (delta < 0.0) {
+ return (-1 * sign);
+ } else if (delta > 0.0) {
+ return (1 * sign);
+ }
+ }
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_SortMap --
+ *
+ * Returns an array of indices that represents the sorted mapping of the
+ * original vector.
+ *
+ * Results:
+ * A standard TCL result. If any of the auxiliary vectors are a
+ * different size than the sorted vector object, TCL_ERROR is returned.
+ * Otherwise TCL_OK is returned.
+ *
+ * Side Effects:
+ * The vectors are sorted.
+ *
+ * vecName sort ?switches? vecName vecName...
+ *---------------------------------------------------------------------------
+ */
+size_t *
+Blt_Vec_SortMap(Vector **vectors, int nVectors)
+{
+ size_t *map;
+ int i;
+ Vector *vPtr = *vectors;
+ int length;
+
+ length = vPtr->last - vPtr->first + 1;
+ map = malloc(sizeof(size_t) * length);
+ for (i = vPtr->first; i <= vPtr->last; i++) {
+ map[i] = i;
+ }
+ /* Set global variables for sorting routine. */
+ sortVectors = vectors;
+ nSortVectors = nVectors;
+ qsort((char *)map, length, sizeof(size_t),
+ (QSortCompareProc *)CompareVectors);
+ return map;
+}
+
+static size_t *
+SortVectors(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Vector **vectors, *v2Ptr;
+ size_t *map;
+ int i;
+
+ vectors = malloc(sizeof(Vector *) * (objc + 1));
+ vectors[0] = vPtr;
+ map = NULL;
+ for (i = 0; i < objc; i++) {
+ if (Blt_Vec_LookupName(vPtr->dataPtr, Tcl_GetString(objv[i]),
+ &v2Ptr) != TCL_OK) {
+ goto error;
+ }
+ if (v2Ptr->length != vPtr->length) {
+ Tcl_AppendResult(interp, "vector \"", v2Ptr->name,
+ "\" is not the same size as \"", vPtr->name, "\"",
+ (char *)NULL);
+ goto error;
+ }
+ vectors[i + 1] = v2Ptr;
+ }
+ map = Blt_Vec_SortMap(vectors, objc + 1);
+ error:
+ free(vectors);
+ return map;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * SortOp --
+ *
+ * Sorts the vector object and any other vectors according to sorting
+ * order of the vector object.
+ *
+ * Results:
+ * A standard TCL result. If any of the auxiliary vectors are a
+ * different size than the sorted vector object, TCL_ERROR is returned.
+ * Otherwise TCL_OK is returned.
+ *
+ * Side Effects:
+ * The vectors are sorted.
+ *
+ * vecName sort ?switches? vecName vecName...
+ *---------------------------------------------------------------------------
+ */
+static int
+SortOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ Vector *v2Ptr;
+ double *copy;
+ size_t *map;
+ size_t sortLength, nBytes;
+ int result;
+ int i;
+ unsigned int n;
+ SortSwitches switches;
+
+ sortDecreasing = FALSE;
+ switches.flags = 0;
+ i = Blt_ParseSwitches(interp, sortSwitches, objc - 2, objv + 2, &switches,
+ BLT_SWITCH_OBJV_PARTIAL);
+ if (i < 0) {
+ return TCL_ERROR;
+ }
+ objc -= i, objv += i;
+ sortDecreasing = (switches.flags & SORT_DECREASING);
+ if (objc > 2) {
+ map = SortVectors(vPtr, interp, objc - 2, objv + 2);
+ } else {
+ map = Blt_Vec_SortMap(&vPtr, 1);
+ }
+ if (map == NULL) {
+ return TCL_ERROR;
+ }
+ sortLength = vPtr->length;
+ /*
+ * Create an array to store a copy of the current values of the
+ * vector. We'll merge the values back into the vector based upon the
+ * indices found in the index array.
+ */
+ nBytes = sizeof(double) * sortLength;
+ copy = malloc(nBytes);
+ memcpy((char *)copy, (char *)vPtr->valueArr, nBytes);
+ if (switches.flags & SORT_UNIQUE) {
+ int count;
+
+ for (count = n = 1; n < sortLength; n++) {
+ size_t next, prev;
+
+ next = map[n];
+ prev = map[n - 1];
+ if (copy[next] != copy[prev]) {
+ map[count] = next;
+ count++;
+ }
+ }
+ sortLength = count;
+ nBytes = sortLength * sizeof(double);
+ }
+ if (sortLength != vPtr->length) {
+ Blt_Vec_SetLength(interp, vPtr, sortLength);
+ }
+ for (n = 0; n < sortLength; n++) {
+ vPtr->valueArr[n] = copy[map[n]];
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+
+ /* Now sort any other vectors in the same fashion. The vectors must be
+ * the same size as the map though. */
+ result = TCL_ERROR;
+ for (i = 2; i < objc; i++) {
+ if (Blt_Vec_LookupName(vPtr->dataPtr, Tcl_GetString(objv[i]),
+ &v2Ptr) != TCL_OK) {
+ goto error;
+ }
+ if (sortLength != v2Ptr->length) {
+ Blt_Vec_SetLength(interp, v2Ptr, sortLength);
+ }
+ memcpy((char *)copy, (char *)v2Ptr->valueArr, nBytes);
+ for (n = 0; n < sortLength; n++) {
+ v2Ptr->valueArr[n] = copy[map[n]];
+ }
+ Blt_Vec_UpdateClients(v2Ptr);
+ if (v2Ptr->flush) {
+ Blt_Vec_FlushCache(v2Ptr);
+ }
+ }
+ result = TCL_OK;
+ error:
+ free(copy);
+ free(map);
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * InstExprOp --
+ *
+ * Computes the result of the expression which may be either a scalar
+ * (single value) or vector (list of values).
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+InstExprOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+
+ if (Blt_ExprVector(interp, Tcl_GetString(objv[2]), (Blt_Vector *)vPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ArithOp --
+ *
+ * Results:
+ * A standard TCL result. If the source vector doesn't exist or the
+ * source list is not a valid list of numbers, TCL_ERROR returned.
+ * Otherwise TCL_OK is returned.
+ *
+ * Side Effects:
+ * The vector data is reset. Clients of the vector are notified.
+ * Any cached array indices are flushed.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+ArithOp(Vector *vPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv)
+{
+ double value;
+ int i;
+ Vector *v2Ptr;
+ double scalar;
+ Tcl_Obj *listObjPtr;
+ char *string;
+
+ v2Ptr = Blt_Vec_ParseElement((Tcl_Interp *)NULL, vPtr->dataPtr,
+ Tcl_GetString(objv[2]), NULL, NS_SEARCH_BOTH);
+ if (v2Ptr != NULL) {
+ int j;
+ int length;
+
+ length = v2Ptr->last - v2Ptr->first + 1;
+ if (length != vPtr->length) {
+ Tcl_AppendResult(interp, "vectors \"", Tcl_GetString(objv[0]),
+ "\" and \"", Tcl_GetString(objv[2]),
+ "\" are not the same length", (char *)NULL);
+ return TCL_ERROR;
+ }
+ string = Tcl_GetString(objv[1]);
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ switch (string[0]) {
+ case '*':
+ for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
+ value = vPtr->valueArr[i] * v2Ptr->valueArr[j];
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '/':
+ for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
+ value = vPtr->valueArr[i] / v2Ptr->valueArr[j];
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '-':
+ for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
+ value = vPtr->valueArr[i] - v2Ptr->valueArr[j];
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '+':
+ for (i = 0, j = v2Ptr->first; i < vPtr->length; i++, j++) {
+ value = vPtr->valueArr[i] + v2Ptr->valueArr[j];
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+
+ } else if (Blt_ExprDoubleFromObj(interp, objv[2], &scalar) == TCL_OK) {
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ string = Tcl_GetString(objv[1]);
+ switch (string[0]) {
+ case '*':
+ for (i = 0; i < vPtr->length; i++) {
+ value = vPtr->valueArr[i] * scalar;
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '/':
+ for (i = 0; i < vPtr->length; i++) {
+ value = vPtr->valueArr[i] / scalar;
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '-':
+ for (i = 0; i < vPtr->length; i++) {
+ value = vPtr->valueArr[i] - scalar;
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+
+ case '+':
+ for (i = 0; i < vPtr->length; i++) {
+ value = vPtr->valueArr[i] + scalar;
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewDoubleObj(value));
+ }
+ break;
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ } else {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorInstCmd --
+ *
+ * Parses and invokes the appropriate vector instance command option.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_OpSpec vectorInstOps[] =
+{
+ {"*", 1, ArithOp, 3, 3, "item",}, /*Deprecated*/
+ {"+", 1, ArithOp, 3, 3, "item",}, /*Deprecated*/
+ {"-", 1, ArithOp, 3, 3, "item",}, /*Deprecated*/
+ {"/", 1, ArithOp, 3, 3, "item",}, /*Deprecated*/
+ {"append", 1, AppendOp, 3, 0, "item ?item...?",},
+ {"binread", 1, BinreadOp, 3, 0, "channel ?numValues? ?flags?",},
+ {"clear", 1, ClearOp, 2, 2, "",},
+ {"delete", 2, DeleteOp, 2, 0, "index ?index...?",},
+ {"dup", 2, DupOp, 3, 0, "vecName",},
+ {"expr", 1, InstExprOp, 3, 3, "expression",},
+ {"fft", 1, FFTOp, 3, 0, "vecName ?switches?",},
+ {"index", 3, IndexOp, 3, 4, "index ?value?",},
+ {"inversefft",3, InverseFFTOp,4, 4, "vecName vecName",},
+ {"length", 1, LengthOp, 2, 3, "?newSize?",},
+ {"max", 2, MaxOp, 2, 2, "",},
+ {"merge", 2, MergeOp, 3, 0, "vecName ?vecName...?",},
+ {"min", 2, MinOp, 2, 2, "",},
+ {"normalize", 3, NormalizeOp, 2, 3, "?vecName?",}, /*Deprecated*/
+ {"notify", 3, NotifyOp, 3, 3, "keyword",},
+ {"offset", 1, OffsetOp, 2, 3, "?offset?",},
+ {"populate", 1, PopulateOp, 4, 4, "vecName density",},
+ {"random", 4, RandomOp, 2, 2, "",}, /*Deprecated*/
+ {"range", 4, RangeOp, 2, 4, "first last",},
+ {"search", 3, SearchOp, 3, 5, "?-value? value ?value?",},
+ {"seq", 3, SeqOp, 4, 5, "begin end ?num?",},
+ {"set", 3, SetOp, 3, 3, "list",},
+ {"simplify", 2, SimplifyOp, 2, 2, },
+ {"sort", 2, SortOp, 2, 0, "?switches? ?vecName...?",},
+ {"split", 2, SplitOp, 2, 0, "?vecName...?",},
+ {"values", 3, ValuesOp, 2, 0, "?switches?",},
+ {"variable", 3, MapOp, 2, 3, "?varName?",},
+};
+
+static int nInstOps = sizeof(vectorInstOps) / sizeof(Blt_OpSpec);
+
+int
+Blt_Vec_InstCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const *objv)
+{
+ VectorCmdProc *proc;
+ Vector *vPtr = clientData;
+
+ vPtr->first = 0;
+ vPtr->last = vPtr->length - 1;
+ proc = Blt_GetOpFromObj(interp, nInstOps, vectorInstOps, BLT_OP_ARG1, objc,
+ objv, 0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ return (*proc) (vPtr, interp, objc, objv);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_VarTrace --
+ *
+ * Results:
+ * Returns NULL on success. Only called from a variable trace.
+ *
+ * Side effects:
+ *
+ *---------------------------------------------------------------------------
+ */
+char *
+Blt_Vec_VarTrace(ClientData clientData, Tcl_Interp *interp, const char *part1,
+ const char *part2, int flags)
+{
+ Blt_VectorIndexProc *indexProc;
+ Vector *vPtr = clientData;
+ int first, last;
+ int varFlags;
+#define MAX_ERR_MSG 1023
+ static char message[MAX_ERR_MSG + 1];
+
+ if (part2 == NULL) {
+ if (flags & TCL_TRACE_UNSETS) {
+ free((void*)(vPtr->arrayName));
+ vPtr->arrayName = NULL;
+ if (vPtr->freeOnUnset) {
+ Blt_Vec_Free(vPtr);
+ }
+ }
+ return NULL;
+ }
+ if (Blt_Vec_GetIndexRange(interp, vPtr, part2, INDEX_ALL_FLAGS, &indexProc)
+ != TCL_OK) {
+ goto error;
+ }
+ first = vPtr->first, last = vPtr->last;
+ varFlags = TCL_LEAVE_ERR_MSG | (TCL_GLOBAL_ONLY & flags);
+ if (flags & TCL_TRACE_WRITES) {
+ double value;
+ Tcl_Obj *objPtr;
+
+ if (first == SPECIAL_INDEX) { /* Tried to set "min" or "max" */
+ return (char *)"read-only index";
+ }
+ objPtr = Tcl_GetVar2Ex(interp, part1, part2, varFlags);
+ if (objPtr == NULL) {
+ goto error;
+ }
+ if (Blt_ExprDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ if ((last == first) && (first >= 0)) {
+ /* Single numeric index. Reset the array element to
+ * its old value on errors */
+ Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags);
+ }
+ goto error;
+ }
+ if (first == vPtr->length) {
+ if (Blt_Vec_ChangeLength((Tcl_Interp *)NULL, vPtr, vPtr->length + 1)
+ != TCL_OK) {
+ return (char *)"error resizing vector";
+ }
+ }
+ /* Set possibly an entire range of values */
+ ReplicateValue(vPtr, first, last, value);
+ } else if (flags & TCL_TRACE_READS) {
+ double value;
+ Tcl_Obj *objPtr;
+
+ if (vPtr->length == 0) {
+ if (Tcl_SetVar2(interp, part1, part2, "", varFlags) == NULL) {
+ goto error;
+ }
+ return NULL;
+ }
+ if (first == vPtr->length) {
+ return (char *)"write-only index";
+ }
+ if (first == last) {
+ if (first >= 0) {
+ value = vPtr->valueArr[first];
+ } else {
+ vPtr->first = 0, vPtr->last = vPtr->length - 1;
+ value = (*indexProc) ((Blt_Vector *) vPtr);
+ }
+ objPtr = Tcl_NewDoubleObj(value);
+ if (Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags) == NULL) {
+ Tcl_DecrRefCount(objPtr);
+ goto error;
+ }
+ } else {
+ objPtr = GetValues(vPtr, first, last);
+ if (Tcl_SetVar2Ex(interp, part1, part2, objPtr, varFlags) == NULL) {
+ Tcl_DecrRefCount(objPtr);
+ goto error;
+ }
+ }
+ } else if (flags & TCL_TRACE_UNSETS) {
+ int i, j;
+
+ if ((first == vPtr->length) || (first == SPECIAL_INDEX)) {
+ return (char *)"special vector index";
+ }
+ /*
+ * Collapse the vector from the point of the first unset element.
+ * Also flush any array variable entries so that the shift is
+ * reflected when the array variable is read.
+ */
+ for (i = first, j = last + 1; j < vPtr->length; i++, j++) {
+ vPtr->valueArr[i] = vPtr->valueArr[j];
+ }
+ vPtr->length -= ((last - first) + 1);
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ } else {
+ return (char *)"unknown variable trace flag";
+ }
+ if (flags & (TCL_TRACE_UNSETS | TCL_TRACE_WRITES)) {
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ Tcl_ResetResult(interp);
+ return NULL;
+
+ error:
+ strncpy(message, Tcl_GetStringResult(interp), MAX_ERR_MSG);
+ message[MAX_ERR_MSG] = '\0';
+ return message;
+}
diff --git a/tlt3.0/bltVecInt.h b/tlt3.0/bltVecInt.h
new file mode 100644
index 0000000..a01c8c8
--- /dev/null
+++ b/tlt3.0/bltVecInt.h
@@ -0,0 +1,250 @@
+/*
+ * bltVecInt.h --
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#include "bltInt.h"
+#include <bltHash.h>
+#include <bltChain.h>
+#include <bltVector.h>
+
+#define VECTOR_THREAD_KEY "BLT Vector Data"
+#define VECTOR_MAGIC ((unsigned int) 0x46170277)
+
+/* These defines allow parsing of different types of indices */
+
+#define INDEX_SPECIAL (1<<0) /* Recognize "min", "max", and "++end" as
+ * valid indices */
+#define INDEX_COLON (1<<1) /* Also recognize a range of indices separated
+ * by a colon */
+#define INDEX_CHECK (1<<2) /* Verify that the specified index or range of
+ * indices are within limits */
+#define INDEX_ALL_FLAGS (INDEX_SPECIAL | INDEX_COLON | INDEX_CHECK)
+
+#define SPECIAL_INDEX -2
+
+#define FFT_NO_CONSTANT (1<<0)
+#define FFT_BARTLETT (1<<1)
+#define FFT_SPECTRUM (1<<2)
+
+typedef struct {
+ Blt_HashTable vectorTable; /* Table of vectors */
+ Blt_HashTable mathProcTable; /* Table of vector math functions */
+ Blt_HashTable indexProcTable;
+ Tcl_Interp *interp;
+ unsigned int nextId;
+} VectorInterpData;
+
+/*
+ * Vector --
+ *
+ * A vector is an array of double precision values. It can be accessed
+ * through a TCL command, a TCL array variable, or C API. The storage for
+ * the array points initially to a statically allocated buffer, but to
+ * malloc-ed memory if more is necessary.
+ *
+ * Vectors can be shared by several clients (for example, two different
+ * graph widgets). The data is shared. When a client wants to use a
+ * vector, it allocates a vector identifier, which identifies the client.
+ * Clients use this ID to specify a callback routine to be invoked
+ * whenever the vector is modified or destroyed. Whenever the vector is
+ * updated or destroyed, each client is notified of the change by their
+ * callback routine.
+ */
+
+typedef struct {
+
+ /*
+ * If you change these fields, make sure you change the definition of
+ * Blt_Vector in bltInt.h and blt.h too.
+ */
+
+ double *valueArr; /* Array of values (malloc-ed) */
+
+ int length; /* Current number of values in the array. */
+
+ int size; /* Maximum number of values that can be stored
+ * in the value array. */
+
+ double min, max; /* Minimum and maximum values in the vector */
+
+ int dirty; /* Indicates if the vector has been updated */
+
+ int reserved;
+
+ /* The following fields are local to this module */
+
+ const char *name; /* The namespace-qualified name of the vector.
+ * It points to the hash key allocated for the
+ * entry in the vector hash table. */
+
+ VectorInterpData *dataPtr;
+ Tcl_Interp *interp; /* Interpreter associated with the
+ * vector */
+
+ Blt_HashEntry *hashPtr; /* If non-NULL, pointer in a hash table to
+ * track the vectors in use. */
+
+ Tcl_FreeProc *freeProc; /* Address of procedure to call to release
+ * storage for the value array, Optionally can
+ * be one of the following: TCL_STATIC,
+ * TCL_DYNAMIC, or TCL_VOLATILE. */
+
+ const char *arrayName; /* The name of the TCL array variable mapped
+ * to the vector (malloc'ed). If NULL,
+ * indicates that the vector isn't mapped to
+ * any variable */
+
+ Tcl_Namespace *nsPtr; /* Namespace context of the vector itself. */
+
+ int offset; /* Offset from zero of the vector's starting
+ * index */
+
+ Tcl_Command cmdToken; /* Token for vector's TCL command. */
+
+ Blt_Chain chain; /* List of clients using this vector */
+
+ int notifyFlags; /* Notification flags. See definitions
+ * below */
+
+ int varFlags; /* Indicate if the variable is global,
+ * namespace, or local */
+
+ int freeOnUnset; /* For backward compatibility only: If
+ * non-zero, free the vector when its variable
+ * is unset. */
+ int flush;
+
+ int first, last; /* Selected region of vector. This is used
+ * mostly for the math routines */
+} Vector;
+
+#define NOTIFY_UPDATED ((int)BLT_VECTOR_NOTIFY_UPDATE)
+#define NOTIFY_DESTROYED ((int)BLT_VECTOR_NOTIFY_DESTROY)
+
+#define NOTIFY_NEVER (1<<3) /* Never notify clients of updates to
+ * the vector */
+#define NOTIFY_ALWAYS (1<<4) /* Notify clients after each update
+ * of the vector is made */
+#define NOTIFY_WHENIDLE (1<<5) /* Notify clients at the next idle point
+ * that the vector has been updated. */
+
+#define NOTIFY_PENDING (1<<6) /* A do-when-idle notification of the
+ * vector's clients is pending. */
+#define NOTIFY_NOW (1<<7) /* Notify clients of changes once
+ * immediately */
+
+#define NOTIFY_WHEN_MASK (NOTIFY_NEVER|NOTIFY_ALWAYS|NOTIFY_WHENIDLE)
+
+#define UPDATE_RANGE (1<<9) /* The data of the vector has changed.
+ * Update the min and max limits when
+ * they are needed */
+
+#define FindRange(array, first, last, min, max) \
+{ \
+ min = max = 0.0; \
+ if (first <= last) { \
+ register int i; \
+ min = max = array[first]; \
+ for (i = first + 1; i <= last; i++) { \
+ if (min > array[i]) { \
+ min = array[i]; \
+ } else if (max < array[i]) { \
+ max = array[i]; \
+ } \
+ } \
+ } \
+}
+
+extern void Blt_Vec_InstallSpecialIndices(Blt_HashTable *tablePtr);
+
+extern void Blt_Vec_InstallMathFunctions(Blt_HashTable *tablePtr);
+
+extern void Blt_Vec_UninstallMathFunctions(Blt_HashTable *tablePtr);
+
+extern VectorInterpData *Blt_Vec_GetInterpData (Tcl_Interp *interp);
+
+extern double Blt_Vec_Max(Vector *vecObjPtr);
+extern double Blt_Vec_Min(Vector *vecObjPtr);
+
+extern Vector *Blt_Vec_New(VectorInterpData *dataPtr);
+
+extern int Blt_Vec_Duplicate(Vector *destPtr, Vector *srcPtr);
+
+extern int Blt_Vec_SetLength(Tcl_Interp *interp, Vector *vPtr,
+ int length);
+
+extern int Blt_Vec_SetSize(Tcl_Interp *interp, Vector *vPtr,
+ int size);
+
+extern int Blt_Vec_ChangeLength(Tcl_Interp *interp, Vector *vPtr,
+ int length);
+
+extern Vector *Blt_Vec_ParseElement(Tcl_Interp *interp,
+ VectorInterpData *dataPtr, const char *start, const char **endPtr,
+ int flags);
+
+extern void Blt_Vec_Free(Vector *vPtr);
+
+extern size_t *Blt_Vec_SortMap(Vector **vectors, int nVectors);
+
+extern int Blt_Vec_LookupName(VectorInterpData *dataPtr,
+ const char *vecName, Vector **vPtrPtr);
+
+extern Vector *Blt_Vec_Create(VectorInterpData *dataPtr,
+ const char *name, const char *cmdName, const char *varName,
+ int *newPtr);
+
+extern void Blt_Vec_UpdateRange(Vector *vPtr);
+
+extern void Blt_Vec_UpdateClients(Vector *vPtr);
+
+extern void Blt_Vec_FlushCache(Vector *vPtr);
+
+extern int Blt_Vec_Reset(Vector *vPtr, double *dataArr,
+ int nValues, int arraySize, Tcl_FreeProc *freeProc);
+
+extern int Blt_Vec_GetIndex(Tcl_Interp *interp, Vector *vPtr,
+ const char *string, int *indexPtr, int flags,
+ Blt_VectorIndexProc **procPtrPtr);
+
+extern int Blt_Vec_GetIndexRange(Tcl_Interp *interp, Vector *vPtr,
+ const char *string, int flags, Blt_VectorIndexProc **procPtrPtr);
+
+extern int Blt_Vec_MapVariable(Tcl_Interp *interp, Vector *vPtr,
+ const char *name);
+
+extern int Blt_Vec_FFT(Tcl_Interp *interp, Vector *realPtr,
+ Vector *phasesPtr, Vector *freqPtr, double delta,
+ int flags, Vector *srcPtr);
+
+extern int Blt_Vec_InverseFFT(Tcl_Interp *interp, Vector *iSrcPtr,
+ Vector *rDestPtr, Vector *iDestPtr, Vector *srcPtr);
+
+extern Tcl_ObjCmdProc Blt_Vec_InstCmd;
+
+extern Tcl_VarTraceProc Blt_Vec_VarTrace;
+
+extern Tcl_IdleProc Blt_Vec_NotifyClients;
+
diff --git a/tlt3.0/bltVecMath.c b/tlt3.0/bltVecMath.c
new file mode 100644
index 0000000..8c0ad69
--- /dev/null
+++ b/tlt3.0/bltVecMath.c
@@ -0,0 +1,1897 @@
+
+/*
+ * bltVecMath.c --
+ *
+ * This module implements mathematical expressions with vector data
+ * objects.
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <float.h>
+#include <math.h>
+
+#include "bltInt.h"
+#include "bltVecInt.h"
+#include "bltNsUtil.h"
+#include "bltParse.h"
+
+/*
+ * Three types of math functions:
+ *
+ * ComponentProc Function is applied in multiple calls to
+ * each component of the vector.
+ * VectorProc Entire vector is passed, each component is
+ * modified.
+ * ScalarProc Entire vector is passed, single scalar value
+ * is returned.
+ */
+
+typedef double (ComponentProc)(double value);
+typedef int (VectorProc)(Vector *vPtr);
+typedef double (ScalarProc)(Vector *vPtr);
+
+/*
+ * Built-in math functions:
+ */
+typedef int (GenericMathProc) ();
+
+/*
+ * MathFunction --
+ *
+ * Contains information about math functions that can be called
+ * for vectors. The table of math functions is global within the
+ * application. So you can't define two different "sqrt"
+ * functions.
+ */
+typedef struct {
+ const char *name; /* Name of built-in math function. If
+ * NULL, indicates that the function
+ * was user-defined and dynamically
+ * allocated. Function names are
+ * global across all interpreters. */
+
+ void *proc; /* Procedure that implements this math
+ * function. */
+
+ ClientData clientData; /* Argument to pass when invoking the
+ * function. */
+
+} MathFunction;
+
+
+/*
+ * Macros for testing floating-point values for certain special cases:
+ *
+ * IS_NAN Test for not-a-number by comparing a value against itself
+ * IF_INF Test for infinity by comparing against the largest floating
+ * point value.
+ */
+
+#define IS_NAN(v) ((v) != (v))
+
+#ifdef DBL_MAX
+# define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))
+#else
+# define IS_INF(v) 0
+#endif
+
+/* The data structure below is used to describe an expression value,
+ * which can be either a double-precision floating-point value, or a
+ * string. A given number has only one value at a time. */
+
+#define STATIC_STRING_SPACE 150
+
+/*
+ * Tokens --
+ *
+ * The token types are defined below. In addition, there is a
+ * table associating a precedence with each operator. The order
+ * of types is important. Consult the code before changing it.
+ */
+enum Tokens {
+ VALUE, OPEN_PAREN, CLOSE_PAREN, COMMA, END, UNKNOWN,
+ MULT = 8, DIVIDE, MOD, PLUS, MINUS,
+ LEFT_SHIFT, RIGHT_SHIFT,
+ LESS, GREATER, LEQ, GEQ, EQUAL, NEQ,
+ OLD_BIT_AND, EXPONENT, OLD_BIT_OR, OLD_QUESTY, OLD_COLON,
+ AND, OR, UNARY_MINUS, OLD_UNARY_PLUS, NOT, OLD_BIT_NOT
+};
+
+typedef struct {
+ Vector *vPtr;
+ char staticSpace[STATIC_STRING_SPACE];
+ ParseValue pv; /* Used to hold a string value, if any. */
+} Value;
+
+/*
+ * ParseInfo --
+ *
+ * The data structure below describes the state of parsing an
+ * expression. It's passed among the routines in this module.
+ */
+typedef struct {
+ const char *expr; /* The entire right-hand side of the
+ * expression, as originally passed to
+ * Blt_ExprVector. */
+
+ const char *nextPtr; /* Position of the next character to
+ * be scanned from the expression
+ * string. */
+
+ enum Tokens token; /* Type of the last token to be parsed
+ * from nextPtr. See below for
+ * definitions. Corresponds to the
+ * characters just before nextPtr. */
+
+} ParseInfo;
+
+/*
+ * Precedence table. The values for non-operator token types are ignored.
+ */
+static int precTable[] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 12, 12, 12, /* MULT, DIVIDE, MOD */
+ 11, 11, /* PLUS, MINUS */
+ 10, 10, /* LEFT_SHIFT, RIGHT_SHIFT */
+ 9, 9, 9, 9, /* LESS, GREATER, LEQ, GEQ */
+ 8, 8, /* EQUAL, NEQ */
+ 7, /* OLD_BIT_AND */
+ 13, /* EXPONENTIATION */
+ 5, /* OLD_BIT_OR */
+ 4, /* AND */
+ 3, /* OR */
+ 2, /* OLD_QUESTY */
+ 1, /* OLD_COLON */
+ 14, 14, 14, 14 /* UNARY_MINUS, OLD_UNARY_PLUS, NOT,
+ * OLD_BIT_NOT */
+};
+
+
+/*
+ * Forward declarations.
+ */
+
+static int NextValue(Tcl_Interp *interp, ParseInfo *piPtr, int prec,
+ Value *valuePtr);
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Sort --
+ *
+ * A vector math function. Sorts the values of the given
+ * vector.
+ *
+ * Results:
+ * Always TCL_OK.
+ *
+ * Side Effects:
+ * The vector is sorted.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+Sort(Vector *vPtr)
+{
+ size_t *map;
+ double *values;
+ int i;
+
+ map = Blt_Vec_SortMap(&vPtr, 1);
+ values = malloc(sizeof(double) * vPtr->length);
+ for(i = vPtr->first; i <= vPtr->last; i++) {
+ values[i] = vPtr->valueArr[map[i]];
+ }
+ free(map);
+ for (i = vPtr->first; i <= vPtr->last; i++) {
+ vPtr->valueArr[i] = values[i];
+ }
+ free(values);
+ return TCL_OK;
+}
+
+static double
+Length(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+
+ return (double)(vPtr->last - vPtr->first + 1);
+}
+
+double
+Blt_VecMax(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+
+ return Blt_Vec_Max(vPtr);
+}
+
+double
+Blt_VecMin(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+
+ return Blt_Vec_Min(vPtr);
+}
+
+
+static double
+Product(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double prod;
+ double *vp, *vend;
+
+ prod = 1.0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ prod *= *vp;
+ }
+ return prod;
+}
+
+static double
+Sum(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double sum, c;
+ double *vp, *vend;
+
+ /* Kahan summation algorithm */
+
+ vp = vPtr->valueArr + vPtr->first;
+ sum = *vp++;
+ c = 0.0; /* A running compensation for lost
+ * low-order bits.*/
+ for (vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ double y, t;
+
+ y = *vp - c; /* So far, so good: c is zero.*/
+ t = sum + y; /* Alas, sum is big, y small, so
+ * low-order digits of y are lost.*/
+ c = (t - sum) - y; /* (t - sum) recovers the high-order
+ * part of y; subtracting y recovers
+ * -(low part of y) */
+ sum = t;
+ }
+ return sum;
+}
+
+static double
+Mean(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double sum;
+ int n;
+
+ sum = Sum(vectorPtr);
+ n = vPtr->last - vPtr->first + 1;
+ return sum / (double)n;
+}
+
+/*
+ * var = 1/N Sum( (x[i] - mean)^2 )
+ */
+static double
+Variance(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double var, mean;
+ double *vp, *vend;
+ int count;
+
+ mean = Mean(vectorPtr);
+ var = 0.0;
+ count = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ double dx;
+
+ dx = *vp - mean;
+ var += dx * dx;
+ count++;
+ }
+ if (count < 2) {
+ return 0.0;
+ }
+ var /= (double)(count - 1);
+ return var;
+}
+
+/*
+ * skew = Sum( (x[i] - mean)^3 ) / (var^3/2)
+ */
+static double
+Skew(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double diff, var, skew, mean, diffsq;
+ double *vp, *vend;
+ int count;
+
+ mean = Mean(vectorPtr);
+ var = skew = 0.0;
+ count = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ diff = *vp - mean;
+ diff = fabs(diff);
+ diffsq = diff * diff;
+ var += diffsq;
+ skew += diffsq * diff;
+ count++;
+ }
+ if (count < 2) {
+ return 0.0;
+ }
+ var /= (double)(count - 1);
+ skew /= count * var * sqrt(var);
+ return skew;
+}
+
+static double
+StdDeviation(Blt_Vector *vectorPtr)
+{
+ double var;
+
+ var = Variance(vectorPtr);
+ if (var > 0.0) {
+ return sqrt(var);
+ }
+ return 0.0;
+}
+
+
+static double
+AvgDeviation(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double diff, avg, mean;
+ double *vp, *vend;
+ int count;
+
+ mean = Mean(vectorPtr);
+ avg = 0.0;
+ count = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ diff = *vp - mean;
+ avg += fabs(diff);
+ count++;
+ }
+ if (count < 2) {
+ return 0.0;
+ }
+ avg /= (double)count;
+ return avg;
+}
+
+
+static double
+Kurtosis(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double diff, diffsq, kurt, var, mean;
+ double *vp, *vend;
+ int count;
+
+ mean = Mean(vectorPtr);
+ var = kurt = 0.0;
+ count = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ diff = *vp - mean;
+ diffsq = diff * diff;
+ var += diffsq;
+ kurt += diffsq * diffsq;
+ count++;
+ }
+ if (count < 2) {
+ return 0.0;
+ }
+ var /= (double)(count - 1);
+ if (var == 0.0) {
+ return 0.0;
+ }
+ kurt /= (count * var * var);
+ return kurt - 3.0; /* Fisher Kurtosis */
+}
+
+
+static double
+Median(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ size_t *map;
+ double q2;
+ int mid;
+
+ if (vPtr->length == 0) {
+ return -DBL_MAX;
+ }
+ map = Blt_Vec_SortMap(&vPtr, 1);
+ mid = (vPtr->length - 1) / 2;
+
+ /*
+ * Determine Q2 by checking if the number of elements [0..n-1] is
+ * odd or even. If even, we must take the average of the two
+ * middle values.
+ */
+ if (vPtr->length & 1) { /* Odd */
+ q2 = vPtr->valueArr[map[mid]];
+ } else { /* Even */
+ q2 = (vPtr->valueArr[map[mid]] +
+ vPtr->valueArr[map[mid + 1]]) * 0.5;
+ }
+ free(map);
+ return q2;
+}
+
+static double
+Q1(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double q1;
+ size_t *map;
+
+ if (vPtr->length == 0) {
+ return -DBL_MAX;
+ }
+ map = Blt_Vec_SortMap(&vPtr, 1);
+
+ if (vPtr->length < 4) {
+ q1 = vPtr->valueArr[map[0]];
+ } else {
+ int mid, q;
+
+ mid = (vPtr->length - 1) / 2;
+ q = mid / 2;
+
+ /*
+ * Determine Q1 by checking if the number of elements in the
+ * bottom half [0..mid) is odd or even. If even, we must
+ * take the average of the two middle values.
+ */
+ if (mid & 1) { /* Odd */
+ q1 = vPtr->valueArr[map[q]];
+ } else { /* Even */
+ q1 = (vPtr->valueArr[map[q]] +
+ vPtr->valueArr[map[q + 1]]) * 0.5;
+ }
+ }
+ free(map);
+ return q1;
+}
+
+static double
+Q3(Blt_Vector *vectorPtr)
+{
+ Vector *vPtr = (Vector *)vectorPtr;
+ double q3;
+ size_t *map;
+
+ if (vPtr->length == 0) {
+ return -DBL_MAX;
+ }
+
+ map = Blt_Vec_SortMap(&vPtr, 1);
+
+ if (vPtr->length < 4) {
+ q3 = vPtr->valueArr[map[vPtr->length - 1]];
+ } else {
+ int mid, q;
+
+ mid = (vPtr->length - 1) / 2;
+ q = (vPtr->length + mid) / 2;
+
+ /*
+ * Determine Q3 by checking if the number of elements in the
+ * upper half (mid..n-1] is odd or even. If even, we must
+ * take the average of the two middle values.
+ */
+ if (mid & 1) { /* Odd */
+ q3 = vPtr->valueArr[map[q]];
+ } else { /* Even */
+ q3 = (vPtr->valueArr[map[q]] +
+ vPtr->valueArr[map[q + 1]]) * 0.5;
+ }
+ }
+ free(map);
+ return q3;
+}
+
+
+static int
+Norm(Blt_Vector *vector)
+{
+ Vector *vPtr = (Vector *)vector;
+ double norm, range, min, max;
+ int i;
+
+ min = Blt_Vec_Min(vPtr);
+ max = Blt_Vec_Max(vPtr);
+ range = max - min;
+ for (i = 0; i < vPtr->length; i++) {
+ norm = (vPtr->valueArr[i] - min) / range;
+ vPtr->valueArr[i] = norm;
+ }
+ return TCL_OK;
+}
+
+
+static double
+Nonzeros(Blt_Vector *vector)
+{
+ Vector *vPtr = (Vector *)vector;
+ int count;
+ double *vp, *vend;
+
+ count = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ if (*vp == 0.0) {
+ count++;
+ }
+ }
+ return (double) count;
+}
+
+static double
+Fabs(double value)
+{
+ if (value < 0.0) {
+ return -value;
+ }
+ return value;
+}
+
+static double
+Round(double value)
+{
+ if (value < 0.0) {
+ return ceil(value - 0.5);
+ } else {
+ return floor(value + 0.5);
+ }
+}
+
+static double
+Fmod(double x, double y)
+{
+ if (y == 0.0) {
+ return 0.0;
+ }
+ return x - (floor(x / y) * y);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * MathError --
+ *
+ * This procedure is called when an error occurs during a
+ * floating-point operation. It reads errno and sets
+ * interp->result accordingly.
+ *
+ * Results:
+ * Interp->result is set to hold an error message.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+MathError(
+ Tcl_Interp *interp, /* Where to store error message. */
+ double value) /* Value returned after error; used to
+ * distinguish underflows from
+ * overflows. */
+{
+ if ((errno == EDOM) || (value != value)) {
+ Tcl_AppendResult(interp, "domain error: argument not in valid range",
+ (char *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "DOMAIN",
+ Tcl_GetStringResult(interp), (char *)NULL);
+ } else if ((errno == ERANGE) || IS_INF(value)) {
+ if (value == 0.0) {
+ Tcl_AppendResult(interp,
+ "floating-point value too small to represent",
+ (char *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "UNDERFLOW",
+ Tcl_GetStringResult(interp), (char *)NULL);
+ } else {
+ Tcl_AppendResult(interp,
+ "floating-point value too large to represent",
+ (char *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "OVERFLOW",
+ Tcl_GetStringResult(interp), (char *)NULL);
+ }
+ } else {
+ Tcl_AppendResult(interp, "unknown floating-point error, ",
+ "errno = ", Blt_Itoa(errno), (char *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "UNKNOWN",
+ Tcl_GetStringResult(interp), (char *)NULL);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ParseString --
+ *
+ * Given a string (such as one coming from command or variable
+ * substitution), make a Value based on the string. The value
+ * will be a floating-point or integer, if possible, or else it
+ * will just be a copy of the string.
+ *
+ * Results:
+ * TCL_OK is returned under normal circumstances, and TCL_ERROR
+ * is returned if a floating-point overflow or underflow occurred
+ * while reading in a number. The value at *valuePtr is modified
+ * to hold a number, if possible.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+static int
+ParseString(
+ Tcl_Interp *interp, /* Where to store error message. */
+ const char *string, /* String to turn into value. */
+ Value *valuePtr) /* Where to store value information.
+ * Caller must have initialized pv field. */
+{
+ const char *endPtr;
+ double value;
+
+ errno = 0;
+
+ /*
+ * The string can be either a number or a vector. First try to
+ * convert the string to a number. If that fails then see if
+ * we can find a vector by that name.
+ */
+
+ value = strtod(string, (char **)&endPtr);
+ if ((endPtr != string) && (*endPtr == '\0')) {
+ if (errno != 0) {
+ Tcl_ResetResult(interp);
+ MathError(interp, value);
+ return TCL_ERROR;
+ }
+ /* Numbers are stored as single element vectors. */
+ if (Blt_Vec_ChangeLength(interp, valuePtr->vPtr, 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ valuePtr->vPtr->valueArr[0] = value;
+ return TCL_OK;
+ } else {
+ Vector *vPtr;
+
+ while (isspace((unsigned char)(*string))) {
+ string++; /* Skip spaces leading the vector name. */
+ }
+ vPtr = Blt_Vec_ParseElement(interp, valuePtr->vPtr->dataPtr,
+ string, &endPtr, NS_SEARCH_BOTH);
+ if (vPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (*endPtr != '\0') {
+ Tcl_AppendResult(interp, "extra characters after vector",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ /* Copy the designated vector to our temporary. */
+ Blt_Vec_Duplicate(valuePtr->vPtr, vPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * ParseMathFunction --
+ *
+ * This procedure is invoked to parse a math function from an
+ * expression string, carry out the function, and return the
+ * value computed.
+ *
+ * Results:
+ * TCL_OK is returned if all went well and the function's value
+ * was computed successfully. If the name doesn't match any
+ * known math function, returns TCL_RETURN. And if a format error
+ * was found, TCL_ERROR is returned and an error message is left
+ * in interp->result.
+ *
+ * After a successful return piPtr will be updated to point to
+ * the character just after the function call, the token is set
+ * to VALUE, and the value is stored in valuePtr.
+ *
+ * Side effects:
+ * Embedded commands could have arbitrary side-effects.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ParseMathFunction(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ const char *start, /* Start of string to parse */
+ ParseInfo *piPtr, /* Describes the state of the parse.
+ * piPtr->nextPtr must point to the
+ * first character of the function's
+ * name. */
+ Value *valuePtr) /* Where to store value, if that is
+ * what's parsed from string. Caller
+ * must have initialized pv field
+ * correctly. */
+{
+ Blt_HashEntry *hPtr;
+ MathFunction *mathPtr; /* Info about math function. */
+ char *p;
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ GenericMathProc *proc;
+
+ /*
+ * Find the end of the math function's name and lookup the
+ * record for the function.
+ */
+ p = (char *)start;
+ while (isspace((unsigned char)(*p))) {
+ p++;
+ }
+ piPtr->nextPtr = p;
+ while (isalnum((unsigned char)(*p)) || (*p == '_')) {
+ p++;
+ }
+ if (*p != '(') {
+ return TCL_RETURN; /* Must start with open parenthesis */
+ }
+ dataPtr = valuePtr->vPtr->dataPtr;
+ *p = '\0';
+ hPtr = Blt_FindHashEntry(&dataPtr->mathProcTable, piPtr->nextPtr);
+ *p = '(';
+ if (hPtr == NULL) {
+ return TCL_RETURN; /* Name doesn't match any known function */
+ }
+ /* Pick up the single value as the argument to the function */
+ piPtr->token = OPEN_PAREN;
+ piPtr->nextPtr = p + 1;
+ valuePtr->pv.next = valuePtr->pv.buffer;
+ if (NextValue(interp, piPtr, -1, valuePtr) != TCL_OK) {
+ return TCL_ERROR; /* Parse error */
+ }
+ if (piPtr->token != CLOSE_PAREN) {
+ Tcl_AppendResult(interp, "unmatched parentheses in expression \"",
+ piPtr->expr, "\"", (char *)NULL);
+ return TCL_ERROR; /* Missing right parenthesis */
+ }
+ mathPtr = Blt_GetHashValue(hPtr);
+ proc = mathPtr->proc;
+ if ((*proc) (mathPtr->clientData, interp, valuePtr->vPtr) != TCL_OK) {
+ return TCL_ERROR; /* Function invocation error */
+ }
+ piPtr->token = VALUE;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NextToken --
+ *
+ * Lexical analyzer for expression parser: parses a single value,
+ * operator, or other syntactic element from an expression string.
+ *
+ * Results:
+ * TCL_OK is returned unless an error occurred while doing lexical
+ * analysis or executing an embedded command. In that case a
+ * standard TCL error is returned, using interp->result to hold
+ * an error message. In the event of a successful return, the token
+ * and field in piPtr is updated to refer to the next symbol in
+ * the expression string, and the expr field is advanced past that
+ * token; if the token is a value, then the value is stored at
+ * valuePtr.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+NextToken(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ ParseInfo *piPtr, /* Describes the state of the parse. */
+ Value *valuePtr) /* Where to store value, if that is
+ * what's parsed from string. Caller
+ * must have initialized pv field
+ * correctly. */
+{
+ const char *p;
+ const char *endPtr;
+ const char *var;
+ int result;
+
+ p = piPtr->nextPtr;
+ while (isspace((unsigned char)(*p))) {
+ p++;
+ }
+ if (*p == '\0') {
+ piPtr->token = END;
+ piPtr->nextPtr = p;
+ return TCL_OK;
+ }
+ /*
+ * Try to parse the token as a floating-point number. But check
+ * that the first character isn't a "-" or "+", which "strtod"
+ * will happily accept as an unary operator. Otherwise, we might
+ * accidently treat a binary operator as unary by mistake, which
+ * will eventually cause a syntax error.
+ */
+ if ((*p != '-') && (*p != '+')) {
+ double value;
+
+ errno = 0;
+ value = strtod(p, (char **)&endPtr);
+ if (endPtr != p) {
+ if (errno != 0) {
+ MathError(interp, value);
+ return TCL_ERROR;
+ }
+ piPtr->token = VALUE;
+ piPtr->nextPtr = endPtr;
+
+ /*
+ * Save the single floating-point value as an 1-component vector.
+ */
+ if (Blt_Vec_ChangeLength(interp, valuePtr->vPtr, 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ valuePtr->vPtr->valueArr[0] = value;
+ return TCL_OK;
+ }
+ }
+ piPtr->nextPtr = p + 1;
+ switch (*p) {
+ case '$':
+ piPtr->token = VALUE;
+ var = Tcl_ParseVar(interp, p, &endPtr);
+ if (var == NULL) {
+ return TCL_ERROR;
+ }
+ piPtr->nextPtr = endPtr;
+ Tcl_ResetResult(interp);
+ result = ParseString(interp, var, valuePtr);
+ return result;
+
+ case '[':
+ piPtr->token = VALUE;
+ result = Blt_ParseNestedCmd(interp, p + 1, 0, &endPtr, &valuePtr->pv);
+ if (result != TCL_OK) {
+ return result;
+ }
+ piPtr->nextPtr = endPtr;
+ Tcl_ResetResult(interp);
+ result = ParseString(interp, valuePtr->pv.buffer, valuePtr);
+ return result;
+
+ case '"':
+ piPtr->token = VALUE;
+ result = Blt_ParseQuotes(interp, p + 1, '"', 0, &endPtr, &valuePtr->pv);
+ if (result != TCL_OK) {
+ return result;
+ }
+ piPtr->nextPtr = endPtr;
+ Tcl_ResetResult(interp);
+ result = ParseString(interp, valuePtr->pv.buffer, valuePtr);
+ return result;
+
+ case '{':
+ piPtr->token = VALUE;
+ result = Blt_ParseBraces(interp, p + 1, &endPtr, &valuePtr->pv);
+ if (result != TCL_OK) {
+ return result;
+ }
+ piPtr->nextPtr = endPtr;
+ Tcl_ResetResult(interp);
+ result = ParseString(interp, valuePtr->pv.buffer, valuePtr);
+ return result;
+
+ case '(':
+ piPtr->token = OPEN_PAREN;
+ break;
+
+ case ')':
+ piPtr->token = CLOSE_PAREN;
+ break;
+
+ case ',':
+ piPtr->token = COMMA;
+ break;
+
+ case '*':
+ piPtr->token = MULT;
+ break;
+
+ case '/':
+ piPtr->token = DIVIDE;
+ break;
+
+ case '%':
+ piPtr->token = MOD;
+ break;
+
+ case '+':
+ piPtr->token = PLUS;
+ break;
+
+ case '-':
+ piPtr->token = MINUS;
+ break;
+
+ case '^':
+ piPtr->token = EXPONENT;
+ break;
+
+ case '<':
+ switch (*(p + 1)) {
+ case '<':
+ piPtr->nextPtr = p + 2;
+ piPtr->token = LEFT_SHIFT;
+ break;
+ case '=':
+ piPtr->nextPtr = p + 2;
+ piPtr->token = LEQ;
+ break;
+ default:
+ piPtr->token = LESS;
+ break;
+ }
+ break;
+
+ case '>':
+ switch (*(p + 1)) {
+ case '>':
+ piPtr->nextPtr = p + 2;
+ piPtr->token = RIGHT_SHIFT;
+ break;
+ case '=':
+ piPtr->nextPtr = p + 2;
+ piPtr->token = GEQ;
+ break;
+ default:
+ piPtr->token = GREATER;
+ break;
+ }
+ break;
+
+ case '=':
+ if (*(p + 1) == '=') {
+ piPtr->nextPtr = p + 2;
+ piPtr->token = EQUAL;
+ } else {
+ piPtr->token = UNKNOWN;
+ }
+ break;
+
+ case '&':
+ if (*(p + 1) == '&') {
+ piPtr->nextPtr = p + 2;
+ piPtr->token = AND;
+ } else {
+ piPtr->token = UNKNOWN;
+ }
+ break;
+
+ case '|':
+ if (*(p + 1) == '|') {
+ piPtr->nextPtr = p + 2;
+ piPtr->token = OR;
+ } else {
+ piPtr->token = UNKNOWN;
+ }
+ break;
+
+ case '!':
+ if (*(p + 1) == '=') {
+ piPtr->nextPtr = p + 2;
+ piPtr->token = NEQ;
+ } else {
+ piPtr->token = NOT;
+ }
+ break;
+
+ default:
+ piPtr->token = VALUE;
+ result = ParseMathFunction(interp, p, piPtr, valuePtr);
+ if ((result == TCL_OK) || (result == TCL_ERROR)) {
+ return result;
+ } else {
+ Vector *vPtr;
+
+ while (isspace((unsigned char)(*p))) {
+ p++; /* Skip spaces leading the vector name. */
+ }
+ vPtr = Blt_Vec_ParseElement(interp, valuePtr->vPtr->dataPtr,
+ p, &endPtr, NS_SEARCH_BOTH);
+ if (vPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Blt_Vec_Duplicate(valuePtr->vPtr, vPtr);
+ piPtr->nextPtr = endPtr;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * NextValue --
+ *
+ * Parse a "value" from the remainder of the expression in piPtr.
+ *
+ * Results:
+ * Normally TCL_OK is returned. The value of the expression is
+ * returned in *valuePtr. If an error occurred, then interp->result
+ * contains an error message and TCL_ERROR is returned.
+ * InfoPtr->token will be left pointing to the token AFTER the
+ * expression, and piPtr->nextPtr will point to the character just
+ * after the terminating token.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+NextValue(
+ Tcl_Interp *interp, /* Interpreter to use for error reporting. */
+ ParseInfo *piPtr, /* Describes the state of the parse
+ * just before the value (i.e. NextToken will
+ * be called to get first token of value). */
+ int prec, /* Treat any un-parenthesized operator
+ * with precedence <= this as the end
+ * of the expression. */
+ Value *valuePtr) /* Where to store the value of the expression.
+ * Caller must have initialized pv field. */
+{
+ Value value2; /* Second operand for current operator. */
+ int operator; /* Current operator (either unary or binary). */
+ int gotOp; /* Non-zero means already lexed the operator
+ * (while picking up value for unary operator).
+ * Don't lex again. */
+ int result;
+ Vector *vPtr, *v2Ptr;
+ int i;
+
+ /*
+ * There are two phases to this procedure. First, pick off an initial
+ * value. Then, parse (binary operator, value) pairs until done.
+ */
+
+ vPtr = valuePtr->vPtr;
+ v2Ptr = Blt_Vec_New(vPtr->dataPtr);
+ gotOp = FALSE;
+ value2.vPtr = v2Ptr;
+ value2.pv.buffer = value2.pv.next = value2.staticSpace;
+ value2.pv.end = value2.pv.buffer + STATIC_STRING_SPACE - 1;
+ value2.pv.expandProc = Blt_ExpandParseValue;
+ value2.pv.clientData = NULL;
+
+ result = NextToken(interp, piPtr, valuePtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if (piPtr->token == OPEN_PAREN) {
+
+ /* Parenthesized sub-expression. */
+
+ result = NextValue(interp, piPtr, -1, valuePtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if (piPtr->token != CLOSE_PAREN) {
+ Tcl_AppendResult(interp, "unmatched parentheses in expression \"",
+ piPtr->expr, "\"", (char *)NULL);
+ result = TCL_ERROR;
+ goto done;
+ }
+ } else {
+ if (piPtr->token == MINUS) {
+ piPtr->token = UNARY_MINUS;
+ }
+ if (piPtr->token >= UNARY_MINUS) {
+ operator = piPtr->token;
+ result = NextValue(interp, piPtr, precTable[operator], valuePtr);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ gotOp = TRUE;
+ /* Process unary operators. */
+ switch (operator) {
+ case UNARY_MINUS:
+ for(i = 0; i < vPtr->length; i++) {
+ vPtr->valueArr[i] = -(vPtr->valueArr[i]);
+ }
+ break;
+
+ case NOT:
+ for(i = 0; i < vPtr->length; i++) {
+ vPtr->valueArr[i] = (double)(!vPtr->valueArr[i]);
+ }
+ break;
+ default:
+ Tcl_AppendResult(interp, "unknown operator", (char *)NULL);
+ goto error;
+ }
+ } else if (piPtr->token != VALUE) {
+ Tcl_AppendResult(interp, "missing operand", (char *)NULL);
+ goto error;
+ }
+ }
+ if (!gotOp) {
+ result = NextToken(interp, piPtr, &value2);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ }
+ /*
+ * Got the first operand. Now fetch (operator, operand) pairs.
+ */
+ for (;;) {
+ operator = piPtr->token;
+
+ value2.pv.next = value2.pv.buffer;
+ if ((operator < MULT) || (operator >= UNARY_MINUS)) {
+ if ((operator == END) || (operator == CLOSE_PAREN) ||
+ (operator == COMMA)) {
+ result = TCL_OK;
+ goto done;
+ } else {
+ Tcl_AppendResult(interp, "bad operator", (char *)NULL);
+ goto error;
+ }
+ }
+ if (precTable[operator] <= prec) {
+ result = TCL_OK;
+ goto done;
+ }
+ result = NextValue(interp, piPtr, precTable[operator], &value2);
+ if (result != TCL_OK) {
+ goto done;
+ }
+ if ((piPtr->token < MULT) && (piPtr->token != VALUE) &&
+ (piPtr->token != END) && (piPtr->token != CLOSE_PAREN) &&
+ (piPtr->token != COMMA)) {
+ Tcl_AppendResult(interp, "unexpected token in expression",
+ (char *)NULL);
+ goto error;
+ }
+ /*
+ * At this point we have two vectors and an operator.
+ */
+
+ if (v2Ptr->length == 1) {
+ double *opnd;
+ double scalar;
+
+ /*
+ * 2nd operand is a scalar.
+ */
+ scalar = v2Ptr->valueArr[0];
+ opnd = vPtr->valueArr;
+ switch (operator) {
+ case MULT:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] *= scalar;
+ }
+ break;
+
+ case DIVIDE:
+ if (scalar == 0.0) {
+ Tcl_AppendResult(interp, "divide by zero", (char *)NULL);
+ goto error;
+ }
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] /= scalar;
+ }
+ break;
+
+ case PLUS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] += scalar;
+ }
+ break;
+
+ case MINUS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] -= scalar;
+ }
+ break;
+
+ case EXPONENT:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = pow(opnd[i], scalar);
+ }
+ break;
+
+ case MOD:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = Fmod(opnd[i], scalar);
+ }
+ break;
+
+ case LESS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] < scalar);
+ }
+ break;
+
+ case GREATER:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] > scalar);
+ }
+ break;
+
+ case LEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] <= scalar);
+ }
+ break;
+
+ case GEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] >= scalar);
+ }
+ break;
+
+ case EQUAL:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] == scalar);
+ }
+ break;
+
+ case NEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] != scalar);
+ }
+ break;
+
+ case AND:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] && scalar);
+ }
+ break;
+
+ case OR:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] || scalar);
+ }
+ break;
+
+ case LEFT_SHIFT:
+ {
+ int offset;
+
+ offset = (int)scalar % vPtr->length;
+ if (offset > 0) {
+ double *hold;
+ int j;
+
+ hold = malloc(sizeof(double) * offset);
+ for (i = 0; i < offset; i++) {
+ hold[i] = opnd[i];
+ }
+ for (i = offset, j = 0; i < vPtr->length; i++, j++) {
+ opnd[j] = opnd[i];
+ }
+ for (i = 0, j = vPtr->length - offset;
+ j < vPtr->length; i++, j++) {
+ opnd[j] = hold[i];
+ }
+ free(hold);
+ }
+ }
+ break;
+
+ case RIGHT_SHIFT:
+ {
+ int offset;
+
+ offset = (int)scalar % vPtr->length;
+ if (offset > 0) {
+ double *hold;
+ int j;
+
+ hold = malloc(sizeof(double) * offset);
+ for (i = vPtr->length - offset, j = 0;
+ i < vPtr->length; i++, j++) {
+ hold[j] = opnd[i];
+ }
+ for (i = vPtr->length - offset - 1,
+ j = vPtr->length - 1; i >= 0; i--, j--) {
+ opnd[j] = opnd[i];
+ }
+ for (i = 0; i < offset; i++) {
+ opnd[i] = hold[i];
+ }
+ free(hold);
+ }
+ }
+ break;
+
+ default:
+ Tcl_AppendResult(interp, "unknown operator in expression",
+ (char *)NULL);
+ goto error;
+ }
+
+ } else if (vPtr->length == 1) {
+ double *opnd;
+ double scalar;
+
+ /*
+ * 1st operand is a scalar.
+ */
+ scalar = vPtr->valueArr[0];
+ Blt_Vec_Duplicate(vPtr, v2Ptr);
+ opnd = vPtr->valueArr;
+ switch (operator) {
+ case MULT:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] *= scalar;
+ }
+ break;
+
+ case PLUS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] += scalar;
+ }
+ break;
+
+ case DIVIDE:
+ for(i = 0; i < vPtr->length; i++) {
+ if (opnd[i] == 0.0) {
+ Tcl_AppendResult(interp, "divide by zero",
+ (char *)NULL);
+ goto error;
+ }
+ opnd[i] = (scalar / opnd[i]);
+ }
+ break;
+
+ case MINUS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = scalar - opnd[i];
+ }
+ break;
+
+ case EXPONENT:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = pow(scalar, opnd[i]);
+ }
+ break;
+
+ case MOD:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = Fmod(scalar, opnd[i]);
+ }
+ break;
+
+ case LESS:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(scalar < opnd[i]);
+ }
+ break;
+
+ case GREATER:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(scalar > opnd[i]);
+ }
+ break;
+
+ case LEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(scalar >= opnd[i]);
+ }
+ break;
+
+ case GEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(scalar <= opnd[i]);
+ }
+ break;
+
+ case EQUAL:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] == scalar);
+ }
+ break;
+
+ case NEQ:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] != scalar);
+ }
+ break;
+
+ case AND:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] && scalar);
+ }
+ break;
+
+ case OR:
+ for(i = 0; i < vPtr->length; i++) {
+ opnd[i] = (double)(opnd[i] || scalar);
+ }
+ break;
+
+ case LEFT_SHIFT:
+ case RIGHT_SHIFT:
+ Tcl_AppendResult(interp, "second shift operand must be scalar",
+ (char *)NULL);
+ goto error;
+
+ default:
+ Tcl_AppendResult(interp, "unknown operator in expression",
+ (char *)NULL);
+ goto error;
+ }
+ } else {
+ double *opnd1, *opnd2;
+ /*
+ * Carry out the function of the specified operator.
+ */
+ if (vPtr->length != v2Ptr->length) {
+ Tcl_AppendResult(interp, "vectors are different lengths",
+ (char *)NULL);
+ goto error;
+ }
+ opnd1 = vPtr->valueArr, opnd2 = v2Ptr->valueArr;
+ switch (operator) {
+ case MULT:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] *= opnd2[i];
+ }
+ break;
+
+ case DIVIDE:
+ for (i = 0; i < vPtr->length; i++) {
+ if (opnd2[i] == 0.0) {
+ Tcl_AppendResult(interp,
+ "can't divide by 0.0 vector component",
+ (char *)NULL);
+ goto error;
+ }
+ opnd1[i] /= opnd2[i];
+ }
+ break;
+
+ case PLUS:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] += opnd2[i];
+ }
+ break;
+
+ case MINUS:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] -= opnd2[i];
+ }
+ break;
+
+ case MOD:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = Fmod(opnd1[i], opnd2[i]);
+ }
+ break;
+
+ case EXPONENT:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = pow(opnd1[i], opnd2[i]);
+ }
+ break;
+
+ case LESS:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] < opnd2[i]);
+ }
+ break;
+
+ case GREATER:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] > opnd2[i]);
+ }
+ break;
+
+ case LEQ:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] <= opnd2[i]);
+ }
+ break;
+
+ case GEQ:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] >= opnd2[i]);
+ }
+ break;
+
+ case EQUAL:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] == opnd2[i]);
+ }
+ break;
+
+ case NEQ:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] != opnd2[i]);
+ }
+ break;
+
+ case AND:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] && opnd2[i]);
+ }
+ break;
+
+ case OR:
+ for (i = 0; i < vPtr->length; i++) {
+ opnd1[i] = (double)(opnd1[i] || opnd2[i]);
+ }
+ break;
+
+ case LEFT_SHIFT:
+ case RIGHT_SHIFT:
+ Tcl_AppendResult(interp, "second shift operand must be scalar",
+ (char *)NULL);
+ goto error;
+
+ default:
+ Tcl_AppendResult(interp, "unknown operator in expression",
+ (char *)NULL);
+ goto error;
+ }
+ }
+ }
+ done:
+ if (value2.pv.buffer != value2.staticSpace) {
+ free(value2.pv.buffer);
+ }
+ Blt_Vec_Free(v2Ptr);
+ return result;
+
+ error:
+ if (value2.pv.buffer != value2.staticSpace) {
+ free(value2.pv.buffer);
+ }
+ Blt_Vec_Free(v2Ptr);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * EvaluateExpression --
+ *
+ * This procedure provides top-level functionality shared by
+ * procedures like Tcl_ExprInt, Tcl_ExprDouble, etc.
+ *
+ * Results:
+ * The result is a standard TCL return value. If an error
+ * occurs then an error message is left in interp->result.
+ * The value of the expression is returned in *valuePtr, in
+ * whatever form it ends up in (could be string or integer
+ * or double). Caller may need to convert result. Caller
+ * is also responsible for freeing string memory in *valuePtr,
+ * if any was allocated.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+EvaluateExpression(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ char *string, /* Expression to evaluate. */
+ Value *valuePtr) /* Where to store result. Should
+ * not be initialized by caller. */
+{
+ ParseInfo info;
+ int result;
+ Vector *vPtr;
+ double *vp, *vend;
+
+ info.expr = info.nextPtr = string;
+ valuePtr->pv.buffer = valuePtr->pv.next = valuePtr->staticSpace;
+ valuePtr->pv.end = valuePtr->pv.buffer + STATIC_STRING_SPACE - 1;
+ valuePtr->pv.expandProc = Blt_ExpandParseValue;
+ valuePtr->pv.clientData = NULL;
+
+ result = NextValue(interp, &info, -1, valuePtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (info.token != END) {
+ Tcl_AppendResult(interp, ": syntax error in expression \"",
+ string, "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ vPtr = valuePtr->vPtr;
+
+ /* Check for NaN's and overflows. */
+ for (vp = vPtr->valueArr, vend = vp + vPtr->length; vp < vend; vp++) {
+ if (!isfinite(*vp)) {
+ /*
+ * IEEE floating-point error.
+ */
+ MathError(interp, *vp);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Math Functions --
+ *
+ * This page contains the procedures that implement all of the
+ * built-in math functions for expressions.
+ *
+ * Results:
+ * Each procedure returns TCL_OK if it succeeds and places result
+ * information at *resultPtr. If it fails it returns TCL_ERROR
+ * and leaves an error message in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+ComponentFunc(
+ ClientData clientData, /* Contains address of procedure that
+ * takes one double argument and
+ * returns a double result. */
+ Tcl_Interp *interp,
+ Vector *vPtr)
+{
+ ComponentProc *procPtr = (ComponentProc *) clientData;
+ double *vp, *vend;
+
+ errno = 0;
+ for(vp = vPtr->valueArr + vPtr->first,
+ vend = vPtr->valueArr + vPtr->last; vp <= vend; vp++) {
+ *vp = (*procPtr) (*vp);
+ if (errno != 0) {
+ MathError(interp, *vp);
+ return TCL_ERROR;
+ }
+ if (!isfinite(*vp)) {
+ /*
+ * IEEE floating-point error.
+ */
+ MathError(interp, *vp);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+static int
+ScalarFunc(ClientData clientData, Tcl_Interp *interp, Vector *vPtr)
+{
+ double value;
+ ScalarProc *procPtr = (ScalarProc *) clientData;
+
+ errno = 0;
+ value = (*procPtr) (vPtr);
+ if (errno != 0) {
+ MathError(interp, value);
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_ChangeLength(interp, vPtr, 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vPtr->valueArr[0] = value;
+ return TCL_OK;
+}
+
+/*ARGSUSED*/
+static int
+VectorFunc(ClientData clientData, Tcl_Interp *interp, Vector *vPtr)
+{
+ VectorProc *procPtr = (VectorProc *) clientData;
+
+ return (*procPtr) (vPtr);
+}
+
+
+static MathFunction mathFunctions[] =
+{
+ {"abs", ComponentFunc, Fabs},
+ {"acos", ComponentFunc, acos},
+ {"asin", ComponentFunc, asin},
+ {"atan", ComponentFunc, atan},
+ {"adev", ScalarFunc, AvgDeviation},
+ {"ceil", ComponentFunc, ceil},
+ {"cos", ComponentFunc, cos},
+ {"cosh", ComponentFunc, cosh},
+ {"exp", ComponentFunc, exp},
+ {"floor", ComponentFunc, floor},
+ {"kurtosis",ScalarFunc, Kurtosis},
+ {"length", ScalarFunc, Length},
+ {"log", ComponentFunc, log},
+ {"log10", ComponentFunc, log10},
+ {"max", ScalarFunc, Blt_VecMax},
+ {"mean", ScalarFunc, Mean},
+ {"median", ScalarFunc, Median},
+ {"min", ScalarFunc, Blt_VecMin},
+ {"norm", VectorFunc, Norm},
+ {"nz", ScalarFunc, Nonzeros},
+ {"q1", ScalarFunc, Q1},
+ {"q3", ScalarFunc, Q3},
+ {"prod", ScalarFunc, Product},
+ {"random", ComponentFunc, drand48},
+ {"round", ComponentFunc, Round},
+ {"sdev", ScalarFunc, StdDeviation},
+ {"sin", ComponentFunc, sin},
+ {"sinh", ComponentFunc, sinh},
+ {"skew", ScalarFunc, Skew},
+ {"sort", VectorFunc, Sort},
+ {"sqrt", ComponentFunc, sqrt},
+ {"sum", ScalarFunc, Sum},
+ {"tan", ComponentFunc, tan},
+ {"tanh", ComponentFunc, tanh},
+ {"var", ScalarFunc, Variance},
+ {(char *)NULL,},
+};
+
+void
+Blt_Vec_InstallMathFunctions(Blt_HashTable *tablePtr)
+{
+ MathFunction *mathPtr;
+
+ for (mathPtr = mathFunctions; mathPtr->name != NULL; mathPtr++) {
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ hPtr = Blt_CreateHashEntry(tablePtr, mathPtr->name, &isNew);
+ Blt_SetHashValue(hPtr, (ClientData)mathPtr);
+ }
+}
+
+void
+Blt_Vec_UninstallMathFunctions(Blt_HashTable *tablePtr)
+{
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(tablePtr, &cursor); hPtr != NULL;
+ hPtr = Blt_NextHashEntry(&cursor)) {
+ MathFunction *mathPtr;
+
+ mathPtr = Blt_GetHashValue(hPtr);
+ if (mathPtr->name == NULL) {
+ free(mathPtr);
+ }
+ }
+}
+
+
+static void
+InstallIndexProc(
+ Blt_HashTable *tablePtr,
+ const char *string,
+ Blt_VectorIndexProc *procPtr) /* Pointer to function to be called
+ * when the vector finds the named index.
+ * If NULL, this indicates to remove
+ * the index from the table.
+ */
+{
+ Blt_HashEntry *hPtr;
+ int dummy;
+
+ hPtr = Blt_CreateHashEntry(tablePtr, string, &dummy);
+ if (procPtr == NULL) {
+ Blt_DeleteHashEntry(tablePtr, hPtr);
+ } else {
+ Blt_SetHashValue(hPtr, (ClientData)procPtr);
+ }
+}
+
+void
+Blt_Vec_InstallSpecialIndices(Blt_HashTable *tablePtr)
+{
+ InstallIndexProc(tablePtr, "min", Blt_VecMin);
+ InstallIndexProc(tablePtr, "max", Blt_VecMax);
+ InstallIndexProc(tablePtr, "mean", Mean);
+ InstallIndexProc(tablePtr, "sum", Sum);
+ InstallIndexProc(tablePtr, "prod", Product);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ExprVector --
+ *
+ * Evaluates an vector expression and returns its value(s).
+ *
+ * Results:
+ * Each of the procedures below returns a standard TCL result.
+ * If an error occurs then an error message is left in
+ * interp->result. Otherwise the value of the expression,
+ * in the appropriate form, is stored at *resultPtr. If
+ * the expression had a result that was incompatible with the
+ * desired form then an error is returned.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ExprVector(
+ Tcl_Interp *interp, /* Context in which to evaluate the
+ * expression. */
+ char *string, /* Expression to evaluate. */
+ Blt_Vector *vector) /* Where to store result. */
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr = (Vector *)vector;
+ Value value;
+
+ dataPtr = (vector != NULL)
+ ? vPtr->dataPtr : Blt_Vec_GetInterpData(interp);
+ value.vPtr = Blt_Vec_New(dataPtr);
+ if (EvaluateExpression(interp, string, &value) != TCL_OK) {
+ Blt_Vec_Free(value.vPtr);
+ return TCL_ERROR;
+ }
+ if (vPtr != NULL) {
+ Blt_Vec_Duplicate(vPtr, value.vPtr);
+ } else {
+ Tcl_Obj *listObjPtr;
+ double *vp, *vend;
+
+ /* No result vector. Put values in interp->result. */
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ for (vp = value.vPtr->valueArr, vend = vp + value.vPtr->length;
+ vp < vend; vp++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(*vp));
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ }
+ Blt_Vec_Free(value.vPtr);
+ return TCL_OK;
+}
diff --git a/tlt3.0/bltVector.c b/tlt3.0/bltVector.c
new file mode 100644
index 0000000..35e2d1a
--- /dev/null
+++ b/tlt3.0/bltVector.c
@@ -0,0 +1,2794 @@
+/*
+ * bltVector.c --
+ *
+ * This module implements vector data objects.
+ *
+ * Copyright 1995-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * TODO:
+ * o Add H. Kirsch's vector binary read operation
+ * x binread file0
+ * x binread -file file0
+ *
+ * o Add ASCII/binary file reader
+ * x read fileName
+ *
+ * o Allow Tcl-based client notifications.
+ * vector x
+ * x notify call Display
+ * x notify delete Display
+ * x notify reorder #1 #2
+ */
+
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <time.h>
+
+#include "bltInt.h"
+#include "bltVecInt.h"
+#include "bltOp.h"
+#include "bltNsUtil.h"
+#include "bltSwitch.h"
+
+#define DEF_ARRAY_SIZE 64
+#define TRACE_ALL (TCL_TRACE_WRITES | TCL_TRACE_READS | TCL_TRACE_UNSETS)
+
+
+#define VECTOR_CHAR(c) ((isalnum((unsigned char)(c))) || \
+ (c == '_') || (c == ':') || (c == '@') || (c == '.'))
+
+/*
+ * VectorClient --
+ *
+ * A vector can be shared by several clients. Each client allocates this
+ * structure that acts as its key for using the vector. Clients can also
+ * designate a callback routine that is executed whenever the vector is
+ * updated or destroyed.
+ *
+ */
+typedef struct {
+ unsigned int magic; /* Magic value designating whether this really
+ * is a vector token or not */
+
+ Vector *serverPtr; /* Pointer to the master record of the vector.
+ * If NULL, indicates that the vector has been
+ * destroyed but as of yet, this client hasn't
+ * recognized it. */
+
+ Blt_VectorChangedProc *proc;/* Routine to call when the contents of the
+ * vector change or the vector is deleted. */
+
+ ClientData clientData; /* Data passed whenever the vector change
+ * procedure is called. */
+
+ Blt_ChainLink link; /* Used to quickly remove this entry from its
+ * server's client chain. */
+} VectorClient;
+
+static Tcl_CmdDeleteProc VectorInstDeleteProc;
+static Tcl_ObjCmdProc VectorCmd;
+static Tcl_InterpDeleteProc VectorInterpDeleteProc;
+
+typedef struct {
+ char *varName; /* Requested variable name. */
+ char *cmdName; /* Requested command name. */
+ int flush; /* Flush */
+ int watchUnset; /* Watch when variable is unset. */
+} CreateSwitches;
+
+static Blt_SwitchSpec createSwitches[] =
+{
+ {BLT_SWITCH_STRING, "-variable", "varName",
+ Blt_Offset(CreateSwitches, varName), BLT_SWITCH_NULL_OK},
+ {BLT_SWITCH_STRING, "-command", "command",
+ Blt_Offset(CreateSwitches, cmdName), BLT_SWITCH_NULL_OK},
+ {BLT_SWITCH_BOOLEAN, "-watchunset", "bool",
+ Blt_Offset(CreateSwitches, watchUnset), 0},
+ {BLT_SWITCH_BOOLEAN, "-flush", "bool",
+ Blt_Offset(CreateSwitches, flush), 0},
+ {BLT_SWITCH_END}
+};
+
+typedef int (VectorCmdProc)(Vector *vecObjPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+
+static Vector *
+FindVectorInNamespace(
+ VectorInterpData *dataPtr, /* Interpreter-specific data. */
+ Blt_ObjectName *objNamePtr)
+{
+ Tcl_DString dString;
+ const char *name;
+ Blt_HashEntry *hPtr;
+
+ name = Blt_MakeQualifiedName(objNamePtr, &dString);
+ hPtr = Blt_FindHashEntry(&dataPtr->vectorTable, name);
+ Tcl_DStringFree(&dString);
+ if (hPtr != NULL) {
+ return Blt_GetHashValue(hPtr);
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * GetVectorObject --
+ *
+ * Searches for the vector associated with the name given. Allow for a
+ * range specification.
+ *
+ * Results:
+ * Returns a pointer to the vector if found, otherwise NULL.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Vector *
+GetVectorObject(
+ VectorInterpData *dataPtr, /* Interpreter-specific data. */
+ const char *name,
+ int flags)
+{
+ Blt_ObjectName objName;
+ Vector *vPtr;
+ Tcl_Interp *interp;
+
+ interp = dataPtr->interp;
+ if (!Blt_ParseObjectName(interp, name, &objName,
+ BLT_NO_ERROR_MSG | BLT_NO_DEFAULT_NS)) {
+ return NULL; /* Can't find namespace. */
+ }
+ vPtr = NULL;
+ if (objName.nsPtr != NULL) {
+ vPtr = FindVectorInNamespace(dataPtr, &objName);
+ } else {
+ if (flags & NS_SEARCH_CURRENT) {
+ objName.nsPtr = Tcl_GetCurrentNamespace(interp);
+ vPtr = FindVectorInNamespace(dataPtr, &objName);
+ }
+ if ((vPtr == NULL) && (flags & NS_SEARCH_GLOBAL)) {
+ objName.nsPtr = Tcl_GetGlobalNamespace(interp);
+ vPtr = FindVectorInNamespace(dataPtr, &objName);
+ }
+ }
+ return vPtr;
+}
+
+void
+Blt_Vec_UpdateRange(Vector *vPtr)
+{
+ double min, max;
+ double *vp, *vend;
+
+ vp = vPtr->valueArr + vPtr->first;
+ vend = vPtr->valueArr + vPtr->last;
+ min = max = *vp++;
+ for (/* empty */; vp <= vend; vp++) {
+ if (min > *vp) {
+ min = *vp;
+ } else if (max < *vp) {
+ max = *vp;
+ }
+ }
+ vPtr->min = min;
+ vPtr->max = max;
+ vPtr->notifyFlags &= ~UPDATE_RANGE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_GetIndex --
+ *
+ * Converts the string representing an index in the vector, to its
+ * numeric value. A valid index may be an numeric string of the string
+ * "end" (indicating the last element in the string).
+ *
+ * Results:
+ * A standard TCL result. If the string is a valid index, TCL_OK is
+ * returned. Otherwise TCL_ERROR is returned and interp->result will
+ * contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_GetIndex(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ const char *string,
+ int *indexPtr,
+ int flags,
+ Blt_VectorIndexProc **procPtrPtr)
+{
+ char c;
+ int value;
+
+ c = string[0];
+
+ /* Treat the index "end" like a numeric index. */
+
+ if ((c == 'e') && (strcmp(string, "end") == 0)) {
+ if (vPtr->length < 1) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "bad index \"end\": vector is empty",
+ (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ *indexPtr = vPtr->length - 1;
+ return TCL_OK;
+ } else if ((c == '+') && (strcmp(string, "++end") == 0)) {
+ *indexPtr = vPtr->length;
+ return TCL_OK;
+ }
+ if (procPtrPtr != NULL) {
+ Blt_HashEntry *hPtr;
+
+ hPtr = Blt_FindHashEntry(&vPtr->dataPtr->indexProcTable, string);
+ if (hPtr != NULL) {
+ *indexPtr = SPECIAL_INDEX;
+ *procPtrPtr = Blt_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ }
+ if (Tcl_GetInt(interp, (char *)string, &value) != TCL_OK) {
+ long int lvalue;
+ /*
+ * Unlike Tcl_GetInt, Tcl_ExprLong needs a valid interpreter, but the
+ * interp passed in may be NULL. So we have to use vPtr->interp and
+ * then reset the result.
+ */
+ if (Tcl_ExprLong(vPtr->interp, (char *)string, &lvalue) != TCL_OK) {
+ Tcl_ResetResult(vPtr->interp);
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "bad index \"", string, "\"",
+ (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ value = (int)lvalue;
+ }
+ /*
+ * Correct the index by the current value of the offset. This makes all
+ * the numeric indices non-negative, which is how we distinguish the
+ * special non-numeric indices.
+ */
+ value -= vPtr->offset;
+
+ if ((value < 0) || ((flags & INDEX_CHECK) && (value >= vPtr->length))) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "index \"", string, "\" is out of range",
+ (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ *indexPtr = (int)value;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_GetIndexRange --
+ *
+ * Converts the string representing an index in the vector, to its
+ * numeric value. A valid index may be an numeric string of the string
+ * "end" (indicating the last element in the string).
+ *
+ * Results:
+ * A standard TCL result. If the string is a valid index, TCL_OK is
+ * returned. Otherwise TCL_ERROR is returned and interp->result will
+ * contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_GetIndexRange(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ const char *string,
+ int flags,
+ Blt_VectorIndexProc **procPtrPtr)
+{
+ int ielem;
+ char *colon;
+
+ colon = NULL;
+ if (flags & INDEX_COLON) {
+ colon = strchr(string, ':');
+ }
+ if (colon != NULL) {
+ if (string == colon) {
+ vPtr->first = 0; /* Default to the first index */
+ } else {
+ int result;
+
+ *colon = '\0';
+ result = Blt_Vec_GetIndex(interp, vPtr, string, &ielem, flags,
+ (Blt_VectorIndexProc **) NULL);
+ *colon = ':';
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vPtr->first = ielem;
+ }
+ if (*(colon + 1) == '\0') {
+ /* Default to the last index */
+ vPtr->last = (vPtr->length > 0) ? vPtr->length - 1 : 0;
+ } else {
+ if (Blt_Vec_GetIndex(interp, vPtr, colon + 1, &ielem, flags,
+ (Blt_VectorIndexProc **) NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vPtr->last = ielem;
+ }
+ if (vPtr->first > vPtr->last) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "bad range \"", string,
+ "\" (first > last)", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ } else {
+ if (Blt_Vec_GetIndex(interp, vPtr, string, &ielem, flags,
+ procPtrPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ vPtr->last = vPtr->first = ielem;
+ }
+ return TCL_OK;
+}
+
+Vector *
+Blt_Vec_ParseElement(
+ Tcl_Interp *interp,
+ VectorInterpData *dataPtr, /* Interpreter-specific data. */
+ const char *start,
+ const char **endPtr,
+ int flags)
+{
+ char *p;
+ char saved;
+ Vector *vPtr;
+
+ p = (char *)start;
+ /* Find the end of the vector name */
+ while (VECTOR_CHAR(*p)) {
+ p++;
+ }
+ saved = *p;
+ *p = '\0';
+
+ vPtr = GetVectorObject(dataPtr, start, flags);
+ if (vPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't find vector \"", start, "\"",
+ (char *)NULL);
+ }
+ *p = saved;
+ return NULL;
+ }
+ *p = saved;
+ vPtr->first = 0;
+ vPtr->last = vPtr->length - 1;
+ if (*p == '(') {
+ int count, result;
+
+ start = p + 1;
+ p++;
+
+ /* Find the matching right parenthesis */
+ count = 1;
+ while (*p != '\0') {
+ if (*p == ')') {
+ count--;
+ if (count == 0) {
+ break;
+ }
+ } else if (*p == '(') {
+ count++;
+ }
+ p++;
+ }
+ if (count > 0) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unbalanced parentheses \"", start,
+ "\"", (char *)NULL);
+ }
+ return NULL;
+ }
+ *p = '\0';
+ result = Blt_Vec_GetIndexRange(interp, vPtr, start,
+ (INDEX_COLON | INDEX_CHECK), (Blt_VectorIndexProc **) NULL);
+ *p = ')';
+ if (result != TCL_OK) {
+ return NULL;
+ }
+ p++;
+ }
+ if (endPtr != NULL) {
+ *endPtr = p;
+ }
+ return vPtr;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_NotifyClients --
+ *
+ * Notifies each client of the vector that the vector has changed
+ * (updated or destroyed) by calling the provided function back. The
+ * function pointer may be NULL, in that case the client is not notified.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The results depend upon what actions the client callbacks
+ * take.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Vec_NotifyClients(ClientData clientData)
+{
+ Vector *vPtr = clientData;
+ Blt_ChainLink link, next;
+ Blt_VectorNotify notify;
+
+ notify = (vPtr->notifyFlags & NOTIFY_DESTROYED)
+ ? BLT_VECTOR_NOTIFY_DESTROY : BLT_VECTOR_NOTIFY_UPDATE;
+ vPtr->notifyFlags &= ~(NOTIFY_UPDATED | NOTIFY_DESTROYED | NOTIFY_PENDING);
+ for (link = Blt_Chain_FirstLink(vPtr->chain); link != NULL; link = next) {
+ VectorClient *clientPtr;
+
+ next = Blt_Chain_NextLink(link);
+ clientPtr = Blt_Chain_GetValue(link);
+ if ((clientPtr->proc != NULL) && (clientPtr->serverPtr != NULL)) {
+ (*clientPtr->proc) (vPtr->interp, clientPtr->clientData, notify);
+ }
+ }
+ /*
+ * Some clients may not handle the "destroy" callback properly (they
+ * should call Blt_FreeVectorId to release the client identifier), so mark
+ * any remaining clients to indicate that vector's server has gone away.
+ */
+ if (notify == BLT_VECTOR_NOTIFY_DESTROY) {
+ for (link = Blt_Chain_FirstLink(vPtr->chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ VectorClient *clientPtr;
+
+ clientPtr = Blt_Chain_GetValue(link);
+ clientPtr->serverPtr = NULL;
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_UpdateClients --
+ *
+ * Notifies each client of the vector that the vector has changed
+ * (updated or destroyed) by calling the provided function back.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The individual client callbacks are eventually invoked.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Vec_UpdateClients(Vector *vPtr)
+{
+ vPtr->dirty++;
+ vPtr->max = vPtr->min = NAN;
+ if (vPtr->notifyFlags & NOTIFY_NEVER) {
+ return;
+ }
+ vPtr->notifyFlags |= NOTIFY_UPDATED;
+ if (vPtr->notifyFlags & NOTIFY_ALWAYS) {
+ Blt_Vec_NotifyClients(vPtr);
+ return;
+ }
+ if (!(vPtr->notifyFlags & NOTIFY_PENDING)) {
+ vPtr->notifyFlags |= NOTIFY_PENDING;
+ Tcl_DoWhenIdle(Blt_Vec_NotifyClients, vPtr);
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_FlushCache --
+ *
+ * Unsets all the elements of the TCL array variable associated with the
+ * vector, freeing memory associated with the variable. This includes
+ * both the hash table and the hash keys. The down side is that this
+ * effectively flushes the caching of vector elements in the array. This
+ * means that the subsequent reads of the array will require a decimal to
+ * string conversion.
+ *
+ * This is needed when the vector changes its values, making the array
+ * variable out-of-sync.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * All elements of array variable (except one) are unset, freeing
+ * the memory associated with the variable.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Vec_FlushCache(Vector *vPtr)
+{
+ Tcl_Interp *interp = vPtr->interp;
+
+ if (vPtr->arrayName == NULL) {
+ return; /* Doesn't use the variable API */
+ }
+ /* Turn off the trace temporarily so that we can unset all the
+ * elements in the array. */
+
+ Tcl_UntraceVar2(interp, vPtr->arrayName, (char *)NULL,
+ TRACE_ALL | vPtr->varFlags, Blt_Vec_VarTrace, vPtr);
+
+ /* Clear all the element entries from the entire array */
+ Tcl_UnsetVar2(interp, vPtr->arrayName, (char *)NULL, vPtr->varFlags);
+
+ /* Restore the "end" index by default and the trace on the entire array */
+ Tcl_SetVar2(interp, vPtr->arrayName, "end", "", vPtr->varFlags);
+ Tcl_TraceVar2(interp, vPtr->arrayName, (char *)NULL,
+ TRACE_ALL | vPtr->varFlags, Blt_Vec_VarTrace, vPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_LookupName --
+ *
+ * Searches for the vector associated with the name given. Allow for a
+ * range specification.
+ *
+ * Results:
+ * Returns a pointer to the vector if found, otherwise NULL. If the name
+ * is not associated with a vector and the TCL_LEAVE_ERR_MSG flag is set,
+ * and interp->result will contain an error message.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_LookupName(
+ VectorInterpData *dataPtr, /* Interpreter-specific data. */
+ const char *vecName,
+ Vector **vPtrPtr)
+{
+ Vector *vPtr;
+ const char *endPtr;
+
+ vPtr = Blt_Vec_ParseElement(dataPtr->interp, dataPtr, vecName, &endPtr,
+ NS_SEARCH_BOTH);
+ if (vPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (*endPtr != '\0') {
+ Tcl_AppendResult(dataPtr->interp,
+ "extra characters after vector name", (char *)NULL);
+ return TCL_ERROR;
+ }
+ *vPtrPtr = vPtr;
+ return TCL_OK;
+}
+
+double
+Blt_Vec_Min(Vector *vecObjPtr)
+{
+ double *vp, *vend;
+ double min;
+
+ vp = vecObjPtr->valueArr + vecObjPtr->first;
+ vend = vecObjPtr->valueArr + vecObjPtr->last;
+ min = *vp++;
+ for (/* empty */; vp <= vend; vp++) {
+ if (min > *vp) {
+ min = *vp;
+ }
+ }
+ vecObjPtr->min = min;
+ return vecObjPtr->min;
+}
+
+double
+Blt_Vec_Max(Vector *vecObjPtr)
+{
+ double max;
+ double *vp, *vend;
+
+ max = NAN;
+ vp = vecObjPtr->valueArr + vecObjPtr->first;
+ vend = vecObjPtr->valueArr + vecObjPtr->last;
+ max = *vp++;
+ for (/* empty */; vp <= vend; vp++) {
+ if (max < *vp) {
+ max = *vp;
+ }
+ }
+ vecObjPtr->max = max;
+ return vecObjPtr->max;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DeleteCommand --
+ *
+ * Deletes the TCL command associated with the vector, without triggering
+ * a callback to "VectorInstDeleteProc".
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+DeleteCommand(Vector *vPtr) /* Vector associated with the TCL command. */
+{
+ Tcl_Interp *interp = vPtr->interp;
+ char *qualName; /* Name of TCL command. */
+ Tcl_CmdInfo cmdInfo;
+ Tcl_DString dString;
+ Blt_ObjectName objName;
+
+ Tcl_DStringInit(&dString);
+ objName.name = Tcl_GetCommandName(interp, vPtr->cmdToken);
+ objName.nsPtr = Blt_GetCommandNamespace(vPtr->cmdToken);
+ qualName = Blt_MakeQualifiedName(&objName, &dString);
+ if (Tcl_GetCommandInfo(interp, qualName, &cmdInfo)) {
+ /* Disable the callback before deleting the TCL command.*/
+ cmdInfo.deleteProc = NULL;
+ Tcl_SetCommandInfo(interp, qualName, &cmdInfo);
+ Tcl_DeleteCommandFromToken(interp, vPtr->cmdToken);
+ }
+ Tcl_DStringFree(&dString);
+ vPtr->cmdToken = 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * UnmapVariable --
+ *
+ * Destroys the trace on the current TCL variable designated to access
+ * the vector.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+UnmapVariable(Vector *vPtr)
+{
+ Tcl_Interp *interp = vPtr->interp;
+
+ /* Unset the entire array */
+ Tcl_UntraceVar2(interp, vPtr->arrayName, (char *)NULL,
+ (TRACE_ALL | vPtr->varFlags), Blt_Vec_VarTrace, vPtr);
+ Tcl_UnsetVar2(interp, vPtr->arrayName, (char *)NULL, vPtr->varFlags);
+
+ if (vPtr->arrayName != NULL) {
+ free((void*)(vPtr->arrayName));
+ vPtr->arrayName = NULL;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_MapVariable --
+ *
+ * Sets up traces on a TCL variable to access the vector.
+ *
+ * If another variable is already mapped, it's first untraced and
+ * removed. Don't do anything else for variables named "" (even though
+ * Tcl allows this pathology). Saves the name of the new array variable.
+ *
+ * Results:
+ * A standard TCL result. If an error occurs setting the variable
+ * TCL_ERROR is returned and an error message is left in the interpreter.
+ *
+ * Side effects:
+ * Traces are set for the new variable. The new variable name is saved in
+ * a malloc'ed string in vPtr->arrayName. If this variable is non-NULL,
+ * it indicates that a TCL variable has been mapped to this vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_MapVariable(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ const char *path)
+{
+ Blt_ObjectName objName;
+ char *newPath;
+ const char *result;
+ Tcl_DString dString;
+
+ if (vPtr->arrayName != NULL) {
+ UnmapVariable(vPtr);
+ }
+ if ((path == NULL) || (path[0] == '\0')) {
+ return TCL_OK; /* If the variable pathname is the empty
+ * string, simply return after removing any
+ * existing variable. */
+ }
+ /* Get the variable name (without the namespace qualifier). */
+ if (!Blt_ParseObjectName(interp, path, &objName, BLT_NO_DEFAULT_NS)) {
+ return TCL_ERROR;
+ }
+ if (objName.nsPtr == NULL) {
+ /*
+ * If there was no namespace qualifier, try harder to see if the
+ * variable is non-local.
+ */
+ objName.nsPtr = Blt_GetVariableNamespace(interp, objName.name);
+ }
+ Tcl_DStringInit(&dString);
+ vPtr->varFlags = 0;
+ if (objName.nsPtr != NULL) { /* Global or namespace variable. */
+ newPath = Blt_MakeQualifiedName(&objName, &dString);
+ vPtr->varFlags |= (TCL_GLOBAL_ONLY);
+ } else { /* Local variable. */
+ newPath = (char *)objName.name;
+ }
+
+ /*
+ * To play it safe, delete the variable first. This has the benefical
+ * side-effect of unmapping the variable from another vector that may be
+ * currently associated with it.
+ */
+ Tcl_UnsetVar2(interp, newPath, (char *)NULL, 0);
+
+ /*
+ * Set the index "end" in the array. This will create the variable
+ * immediately so that we can check its namespace context.
+ */
+ result = Tcl_SetVar2(interp, newPath, "end", "", TCL_LEAVE_ERR_MSG);
+ if (result == NULL) {
+ Tcl_DStringFree(&dString);
+ return TCL_ERROR;
+ }
+ /* Create a full-array trace on reads, writes, and unsets. */
+ Tcl_TraceVar2(interp, newPath, (char *)NULL, TRACE_ALL, Blt_Vec_VarTrace,
+ vPtr);
+ vPtr->arrayName = Blt_Strdup(newPath);
+ Tcl_DStringFree(&dString);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_SetSize --
+ *
+ * Resizes the vector to the designated new size.
+ *
+ * If the new size is the same as the old, simply return. Otherwise
+ * we're copying the data from one memory location to another.
+ *
+ * If the storage changed memory locations, free up the old location if
+ * it was dynamically allocated.
+ *
+ * Results:
+ * A standard TCL result. If the reallocation is successful,
+ * TCL_OK is returned, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * Memory for the array is reallocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_SetSize(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ int newSize) /* Size of array in elements */
+{
+ if (newSize <= 0) {
+ newSize = DEF_ARRAY_SIZE;
+ }
+ if (newSize == vPtr->size) {
+ /* Same size, use the current array. */
+ return TCL_OK;
+ }
+ if (vPtr->freeProc == TCL_DYNAMIC) {
+ double *newArr;
+
+ /* Old memory was dynamically allocated, so use realloc. */
+ newArr = realloc(vPtr->valueArr, newSize * sizeof(double));
+ if (newArr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't reallocate ",
+ Blt_Itoa(newSize), " elements for vector \"",
+ vPtr->name, "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ vPtr->size = newSize;
+ vPtr->valueArr = newArr;
+ return TCL_OK;
+ }
+
+ {
+ double *newArr;
+
+ /* Old memory was created specially (static or special allocator).
+ * Replace with dynamically allocated memory (malloc-ed). */
+
+ newArr = calloc(newSize, sizeof(double));
+ if (newArr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "can't allocate ",
+ Blt_Itoa(newSize), " elements for vector \"",
+ vPtr->name, "\"", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ {
+ int used, wanted;
+
+ /* Copy the contents of the old memory into the new. */
+ used = vPtr->length;
+ wanted = newSize;
+
+ if (used > wanted) {
+ used = wanted;
+ }
+ /* Copy any previous data */
+ if (used > 0) {
+ memcpy(newArr, vPtr->valueArr, used * sizeof(double));
+ }
+ }
+
+ assert(vPtr->valueArr != NULL);
+
+ /*
+ * We're not using the old storage anymore, so free it if it's not
+ * TCL_STATIC. It's static because the user previously reset the
+ * vector with a statically allocated array (setting freeProc to
+ * TCL_STATIC).
+ */
+ if (vPtr->freeProc != TCL_STATIC) {
+ if (vPtr->freeProc == TCL_DYNAMIC) {
+ free(vPtr->valueArr);
+ } else {
+ (*vPtr->freeProc) ((char *)vPtr->valueArr);
+ }
+ }
+ vPtr->freeProc = TCL_DYNAMIC; /* Set the type of the new storage */
+ vPtr->valueArr = newArr;
+ vPtr->size = newSize;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_SetSize --
+ *
+ * Set the length (the number of elements currently in use) of the
+ * vector. If the new length is greater than the size (total number of
+ * slots), then the vector is grown.
+ *
+ * Results:
+ * A standard TCL result. If the reallocation is successful, TCL_OK is
+ * returned, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * Memory for the array is possibly reallocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_SetLength(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ int newLength) /* Size of array in elements */
+{
+ if (vPtr->size < newLength) {
+ if (Blt_Vec_SetSize(interp, vPtr, newLength) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ vPtr->length = newLength;
+ vPtr->first = 0;
+ vPtr->last = newLength - 1;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_ChangeLength --
+ *
+ * Resizes the vector to the new size.
+ *
+ * The new size of the vector is computed by doubling the size of the
+ * vector until it fits the number of slots needed (designated by
+ * *length*).
+ *
+ * If the new size is the same as the old, simply adjust the length of
+ * the vector. Otherwise we're copying the data from one memory location
+ * to another. The trailing elements of the vector need to be reset to
+ * zero.
+ *
+ * If the storage changed memory locations, free up the old location if
+ * it was dynamically allocated.
+ *
+ * Results:
+ * A standard TCL result. If the reallocation is successful,
+ * TCL_OK is returned, otherwise TCL_ERROR.
+ *
+ * Side effects:
+ * Memory for the array is reallocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Blt_Vec_ChangeLength(
+ Tcl_Interp *interp,
+ Vector *vPtr,
+ int newLength)
+{
+ if (newLength < 0) {
+ newLength = 0;
+ }
+ if (newLength > vPtr->size) {
+ int newSize; /* Size of array in elements */
+
+ /* Compute the new size of the array. It's a multiple of
+ * DEF_ARRAY_SIZE. */
+ newSize = DEF_ARRAY_SIZE;
+ while (newSize < newLength) {
+ newSize += newSize;
+ }
+ if (newSize != vPtr->size) {
+ if (Blt_Vec_SetSize(interp, vPtr, newSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ vPtr->length = newLength;
+ vPtr->first = 0;
+ vPtr->last = newLength - 1;
+ return TCL_OK;
+
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_Reset --
+ *
+ * Resets the vector data. This is called by a client to indicate that
+ * the vector data has changed. The vector does not need to point to
+ * different memory. Any clients of the vector will be notified of the
+ * change.
+ *
+ * Results:
+ * A standard TCL result. If the new array size is invalid, TCL_ERROR is
+ * returned. Otherwise TCL_OK is returned and the new vector data is
+ * recorded.
+ *
+ * Side Effects:
+ * Any client designated callbacks will be posted. Memory may be changed
+ * for the vector array.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_Vec_Reset(
+ Vector *vPtr,
+ double *valueArr, /* Array containing the elements of the
+ * vector. If NULL, indicates to reset the
+ * vector size to the default. */
+ int length, /* The number of elements that the vector
+ * currently holds. */
+ int size, /* The maximum number of elements that the
+ * array can hold. */
+ Tcl_FreeProc *freeProc) /* Address of memory deallocation routine
+ * for the array of values. Can also be
+ * TCL_STATIC, TCL_DYNAMIC, or TCL_VOLATILE. */
+{
+ if (vPtr->valueArr != valueArr) { /* New array of values resides
+ * in different memory than
+ * the current vector. */
+ if ((valueArr == NULL) || (size == 0)) {
+ /* Empty array. Set up default values */
+ valueArr = malloc(sizeof(double) * DEF_ARRAY_SIZE);
+ size = DEF_ARRAY_SIZE;
+ if (valueArr == NULL) {
+ Tcl_AppendResult(vPtr->interp, "can't allocate ",
+ Blt_Itoa(size), " elements for vector \"",
+ vPtr->name, "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ freeProc = TCL_DYNAMIC;
+ length = 0;
+ } else if (freeProc == TCL_VOLATILE) {
+ double *newArr;
+ /* Data is volatile. Make a copy of the value array. */
+ newArr = malloc(size * sizeof(double));
+ if (newArr == NULL) {
+ Tcl_AppendResult(vPtr->interp, "can't allocate ",
+ Blt_Itoa(size), " elements for vector \"",
+ vPtr->name, "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ memcpy((char *)newArr, (char *)valueArr,
+ sizeof(double) * length);
+ valueArr = newArr;
+ freeProc = TCL_DYNAMIC;
+ }
+
+ if (vPtr->freeProc != TCL_STATIC) {
+ /* Old data was dynamically allocated. Free it before attaching
+ * new data. */
+ if (vPtr->freeProc == TCL_DYNAMIC) {
+ free(vPtr->valueArr);
+ } else {
+ (*freeProc) ((char *)vPtr->valueArr);
+ }
+ }
+ vPtr->freeProc = freeProc;
+ vPtr->valueArr = valueArr;
+ vPtr->size = size;
+ }
+
+ vPtr->length = length;
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+Vector *
+Blt_Vec_New(VectorInterpData *dataPtr) /* Interpreter-specific data. */
+{
+ Vector *vPtr;
+
+ vPtr = calloc(1, sizeof(Vector));
+ vPtr->valueArr = malloc(sizeof(double) * DEF_ARRAY_SIZE);
+ if (vPtr->valueArr == NULL) {
+ free(vPtr);
+ return NULL;
+ }
+ vPtr->size = DEF_ARRAY_SIZE;
+ vPtr->freeProc = TCL_DYNAMIC;
+ vPtr->length = 0;
+ vPtr->interp = dataPtr->interp;
+ vPtr->hashPtr = NULL;
+ vPtr->chain = Blt_Chain_Create();
+ vPtr->flush = FALSE;
+ vPtr->min = vPtr->max = NAN;
+ vPtr->notifyFlags = NOTIFY_WHENIDLE;
+ vPtr->dataPtr = dataPtr;
+ return vPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_Free --
+ *
+ * Removes the memory and frees resources associated with the vector.
+ *
+ * o Removes the trace and the TCL array variable and unsets
+ * the variable.
+ * o Notifies clients of the vector that the vector is being
+ * destroyed.
+ * o Removes any clients that are left after notification.
+ * o Frees the memory (if necessary) allocated for the array.
+ * o Removes the entry from the hash table of vectors.
+ * o Frees the memory allocated for the name.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_Vec_Free(Vector *vPtr)
+{
+ Blt_ChainLink link;
+
+ if (vPtr->cmdToken != 0) {
+ DeleteCommand(vPtr);
+ }
+ if (vPtr->arrayName != NULL) {
+ UnmapVariable(vPtr);
+ }
+ vPtr->length = 0;
+
+ /* Immediately notify clients that vector is going away */
+ if (vPtr->notifyFlags & NOTIFY_PENDING) {
+ vPtr->notifyFlags &= ~NOTIFY_PENDING;
+ Tcl_CancelIdleCall(Blt_Vec_NotifyClients, vPtr);
+ }
+ vPtr->notifyFlags |= NOTIFY_DESTROYED;
+ Blt_Vec_NotifyClients(vPtr);
+
+ for (link = Blt_Chain_FirstLink(vPtr->chain); link != NULL;
+ link = Blt_Chain_NextLink(link)) {
+ VectorClient *clientPtr;
+
+ clientPtr = Blt_Chain_GetValue(link);
+ free(clientPtr);
+ }
+ Blt_Chain_Destroy(vPtr->chain);
+ if ((vPtr->valueArr != NULL) && (vPtr->freeProc != TCL_STATIC)) {
+ if (vPtr->freeProc == TCL_DYNAMIC) {
+ free(vPtr->valueArr);
+ } else {
+ (*vPtr->freeProc) ((char *)vPtr->valueArr);
+ }
+ }
+ if (vPtr->hashPtr != NULL) {
+ Blt_DeleteHashEntry(&vPtr->dataPtr->vectorTable, vPtr->hashPtr);
+ }
+#ifdef NAMESPACE_DELETE_NOTIFY
+ if (vPtr->nsPtr != NULL) {
+ Blt_DestroyNsDeleteNotify(vPtr->interp, vPtr->nsPtr, vPtr);
+ }
+#endif /* NAMESPACE_DELETE_NOTIFY */
+ free(vPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorInstDeleteProc --
+ *
+ * Deletes the command associated with the vector. This is called only
+ * when the command associated with the vector is destroyed.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static void
+VectorInstDeleteProc(ClientData clientData)
+{
+ Vector *vPtr = clientData;
+
+ vPtr->cmdToken = 0;
+ Blt_Vec_Free(vPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Vec_Create --
+ *
+ * Creates a vector structure and the following items:
+ *
+ * o TCL command
+ * o TCL array variable and establishes traces on the variable
+ * o Adds a new entry in the vector hash table
+ *
+ * Results:
+ * A pointer to the new vector structure. If an error occurred NULL is
+ * returned and an error message is left in interp->result.
+ *
+ * Side effects:
+ * A new TCL command and array variable is added to the interpreter.
+ *
+ * ----------------------------------------------------------------------
+ */
+Vector *
+Blt_Vec_Create(
+ VectorInterpData *dataPtr, /* Interpreter-specific data. */
+ const char *vecName, /* Namespace-qualified name of the vector */
+ const char *cmdName, /* Name of the TCL command mapped to
+ * the vector */
+ const char *varName, /* Name of the TCL array mapped to the
+ * vector */
+ int *isNewPtr)
+{
+ Tcl_DString dString;
+ Vector *vPtr;
+ int isNew;
+ Blt_ObjectName objName;
+ char *qualName;
+ Blt_HashEntry *hPtr;
+ Tcl_Interp *interp = dataPtr->interp;
+
+ isNew = 0;
+ vPtr = NULL;
+
+ if (!Blt_ParseObjectName(interp, vecName, &objName, 0)) {
+ return NULL;
+ }
+ Tcl_DStringInit(&dString);
+ if ((objName.name[0] == '#') && (strcmp(objName.name, "#auto") == 0)) {
+
+ do { /* Generate a unique vector name. */
+ char string[200];
+
+ sprintf_s(string, 200, "vector%d", dataPtr->nextId++);
+ objName.name = string;
+ qualName = Blt_MakeQualifiedName(&objName, &dString);
+ hPtr = Blt_FindHashEntry(&dataPtr->vectorTable, qualName);
+ } while (hPtr != NULL);
+ } else {
+ const char *p;
+
+ for (p = objName.name; *p != '\0'; p++) {
+ if (!VECTOR_CHAR(*p)) {
+ Tcl_AppendResult(interp, "bad vector name \"", objName.name,
+ "\": must contain digits, letters, underscore, or period",
+ (char *)NULL);
+ goto error;
+ }
+ }
+ qualName = Blt_MakeQualifiedName(&objName, &dString);
+ vPtr = Blt_Vec_ParseElement((Tcl_Interp *)NULL, dataPtr, qualName,
+ NULL, NS_SEARCH_CURRENT);
+ }
+ if (vPtr == NULL) {
+ hPtr = Blt_CreateHashEntry(&dataPtr->vectorTable, qualName, &isNew);
+ vPtr = Blt_Vec_New(dataPtr);
+ vPtr->hashPtr = hPtr;
+ vPtr->nsPtr = objName.nsPtr;
+
+ vPtr->name = Blt_GetHashKey(&dataPtr->vectorTable, hPtr);
+#ifdef NAMESPACE_DELETE_NOTIFY
+ Blt_CreateNsDeleteNotify(interp, objName.nsPtr, vPtr,
+ VectorInstDeleteProc);
+#endif /* NAMESPACE_DELETE_NOTIFY */
+ Blt_SetHashValue(hPtr, vPtr);
+ }
+ if (cmdName != NULL) {
+ Tcl_CmdInfo cmdInfo;
+
+ if ((cmdName == vecName) ||
+ ((cmdName[0] == '#') && (strcmp(cmdName, "#auto")==0))) {
+ cmdName = qualName;
+ }
+ if (Tcl_GetCommandInfo(interp, (char *)cmdName, &cmdInfo)) {
+ if (vPtr != cmdInfo.objClientData) {
+ Tcl_AppendResult(interp, "command \"", cmdName,
+ "\" already exists", (char *)NULL);
+ goto error;
+ }
+ /* We get here only if the old name is the same as the new. */
+ goto checkVariable;
+ }
+ }
+ if (vPtr->cmdToken != 0) {
+ DeleteCommand(vPtr); /* Command already exists, delete old first */
+ }
+ if (cmdName != NULL) {
+ Tcl_DString dString2;
+
+ Tcl_DStringInit(&dString2);
+ if (cmdName != qualName) {
+ if (!Blt_ParseObjectName(interp, cmdName, &objName, 0)) {
+ goto error;
+ }
+ cmdName = Blt_MakeQualifiedName(&objName, &dString2);
+ }
+ vPtr->cmdToken = Tcl_CreateObjCommand(interp, (char *)cmdName,
+ Blt_Vec_InstCmd, vPtr, VectorInstDeleteProc);
+ Tcl_DStringFree(&dString2);
+ }
+ checkVariable:
+ if (varName != NULL) {
+ if ((varName[0] == '#') && (strcmp(varName, "#auto") == 0)) {
+ varName = qualName;
+ }
+ if (Blt_Vec_MapVariable(interp, vPtr, varName) != TCL_OK) {
+ goto error;
+ }
+ }
+
+ Tcl_DStringFree(&dString);
+ *isNewPtr = isNew;
+ return vPtr;
+
+ error:
+ Tcl_DStringFree(&dString);
+ if (vPtr != NULL) {
+ Blt_Vec_Free(vPtr);
+ }
+ return NULL;
+}
+
+
+int
+Blt_Vec_Duplicate(Vector *destPtr, Vector *srcPtr)
+{
+ size_t nBytes;
+ size_t length;
+
+ if (destPtr == srcPtr) {
+ /* Copying the same vector. */
+ }
+ length = srcPtr->last - srcPtr->first + 1;
+ if (Blt_Vec_ChangeLength(destPtr->interp, destPtr, length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ nBytes = length * sizeof(double);
+ memcpy(destPtr->valueArr, srcPtr->valueArr + srcPtr->first, nBytes);
+ destPtr->offset = srcPtr->offset;
+ return TCL_OK;
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorNamesOp --
+ *
+ * Reports the names of all the current vectors in the interpreter.
+ *
+ * Results:
+ * A standard TCL result. interp->result will contain a list of
+ * all the names of the vector instances.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+VectorNamesOp(
+ ClientData clientData, /* Interpreter-specific data. */
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ VectorInterpData *dataPtr = clientData;
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);
+ if (objc == 2) {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&dataPtr->vectorTable, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ char *name;
+
+ name = Blt_GetHashKey(&dataPtr->vectorTable, hPtr);
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ } else {
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&dataPtr->vectorTable, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ char *name;
+ int i;
+
+ name = Blt_GetHashKey(&dataPtr->vectorTable, hPtr);
+ for (i = 2; i < objc; i++) {
+ char *pattern;
+
+ pattern = Tcl_GetString(objv[i]);
+ if (Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(name, -1));
+ break;
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorCreateOp --
+ *
+ * Creates a TCL command, and array variable representing an instance of
+ * a vector.
+ *
+ * vector a
+ * vector b(20)
+ * vector c(-5:14)
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*ARGSUSED*/
+static int
+VectorCreate2(
+ ClientData clientData, /* Interpreter-specific data. */
+ Tcl_Interp *interp,
+ int argStart,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ VectorInterpData *dataPtr = clientData;
+ Vector *vPtr;
+ int count, i;
+ CreateSwitches switches;
+
+ /*
+ * Handle switches to the vector command and collect the vector name
+ * arguments into an array.
+ */
+ count = 0;
+ vPtr = NULL;
+ for (i = argStart; i < objc; i++) {
+ char *string;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '-') {
+ break;
+ }
+ }
+ count = i - argStart;
+ if (count == 0) {
+ Tcl_AppendResult(interp, "no vector names supplied", (char *)NULL);
+ return TCL_ERROR;
+ }
+ memset(&switches, 0, sizeof(switches));
+ if (Blt_ParseSwitches(interp, createSwitches, objc - i, objv + i,
+ &switches, BLT_SWITCH_DEFAULTS) < 0) {
+ return TCL_ERROR;
+ }
+ if (count > 1) {
+ if (switches.cmdName != NULL) {
+ Tcl_AppendResult(interp,
+ "can't specify more than one vector with \"-command\" switch",
+ (char *)NULL);
+ goto error;
+ }
+ if (switches.varName != NULL) {
+ Tcl_AppendResult(interp,
+ "can't specify more than one vector with \"-variable\" switch",
+ (char *)NULL);
+ goto error;
+ }
+ }
+ for (i = 0; i < count; i++) {
+ char *leftParen, *rightParen;
+ char *string;
+ int isNew;
+ int size, first, last;
+
+ size = first = last = 0;
+ string = Tcl_GetString(objv[i + argStart]);
+ leftParen = strchr(string, '(');
+ rightParen = strchr(string, ')');
+ if (((leftParen != NULL) && (rightParen == NULL)) ||
+ ((leftParen == NULL) && (rightParen != NULL)) ||
+ (leftParen > rightParen)) {
+ Tcl_AppendResult(interp, "bad vector specification \"", string,
+ "\"", (char *)NULL);
+ goto error;
+ }
+ if (leftParen != NULL) {
+ int result;
+ char *colon;
+
+ *rightParen = '\0';
+ colon = strchr(leftParen + 1, ':');
+ if (colon != NULL) {
+
+ /* Specification is in the form vecName(first:last) */
+ *colon = '\0';
+ result = Tcl_GetInt(interp, leftParen + 1, &first);
+ if ((*(colon + 1) != '\0') && (result == TCL_OK)) {
+ result = Tcl_GetInt(interp, colon + 1, &last);
+ if (first > last) {
+ Tcl_AppendResult(interp, "bad vector range \"",
+ string, "\"", (char *)NULL);
+ result = TCL_ERROR;
+ }
+ size = (last - first) + 1;
+ }
+ *colon = ':';
+ } else {
+ /* Specification is in the form vecName(size) */
+ result = Tcl_GetInt(interp, leftParen + 1, &size);
+ }
+ *rightParen = ')';
+ if (result != TCL_OK) {
+ goto error;
+ }
+ if (size < 0) {
+ Tcl_AppendResult(interp, "bad vector size \"", string, "\"",
+ (char *)NULL);
+ goto error;
+ }
+ }
+ if (leftParen != NULL) {
+ *leftParen = '\0';
+ }
+ /*
+ * By default, we create a TCL command by the name of the vector.
+ */
+ vPtr = Blt_Vec_Create(dataPtr, string,
+ (switches.cmdName == NULL) ? string : switches.cmdName,
+ (switches.varName == NULL) ? string : switches.varName, &isNew);
+ if (leftParen != NULL) {
+ *leftParen = '(';
+ }
+ if (vPtr == NULL) {
+ goto error;
+ }
+ vPtr->freeOnUnset = switches.watchUnset;
+ vPtr->flush = switches.flush;
+ vPtr->offset = first;
+ if (size > 0) {
+ if (Blt_Vec_ChangeLength(interp, vPtr, size) != TCL_OK) {
+ goto error;
+ }
+ }
+ if (!isNew) {
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ }
+ }
+ Blt_FreeSwitches(createSwitches, (char *)&switches, 0);
+ if (vPtr != NULL) {
+ /* Return the name of the last vector created */
+ Tcl_SetStringObj(Tcl_GetObjResult(interp), vPtr->name, -1);
+ }
+ return TCL_OK;
+ error:
+ Blt_FreeSwitches(createSwitches, (char *)&switches, 0);
+ return TCL_ERROR;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorCreateOp --
+ *
+ * Creates a TCL command, and array variable representing an instance of
+ * a vector.
+ *
+ * vector a
+ * vector b(20)
+ * vector c(-5:14)
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+VectorCreateOp(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return VectorCreate2(clientData, interp, 2, objc, objv);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorDestroyOp --
+ *
+ * Destroys the vector and its related TCL command and array variable (if
+ * they exist).
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side effects:
+ * Deletes the vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+VectorDestroyOp(
+ ClientData clientData, /* Interpreter-specific data. */
+ Tcl_Interp *interp, /* Not used. */
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ VectorInterpData *dataPtr = clientData;
+ Vector *vPtr;
+ int i;
+
+ for (i = 2; i < objc; i++) {
+ if (Blt_Vec_LookupName(dataPtr, Tcl_GetString(objv[i]), &vPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_Vec_Free(vPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorExprOp --
+ *
+ * Computes the result of the expression which may be either a scalar
+ * (single value) or vector (list of values).
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+static int
+VectorExprOp(
+ ClientData clientData, /* Not Used. */
+ Tcl_Interp *interp,
+ int objc, /* Not used. */
+ Tcl_Obj *const *objv)
+{
+ return Blt_ExprVector(interp, Tcl_GetString(objv[2]), (Blt_Vector *)NULL);
+}
+
+static Blt_OpSpec vectorCmdOps[] =
+{
+ {"create", 1, VectorCreateOp, 3, 0,
+ "vecName ?vecName...? ?switches...?",},
+ {"destroy", 1, VectorDestroyOp, 3, 0,
+ "vecName ?vecName...?",},
+ {"expr", 1, VectorExprOp, 3, 3, "expression",},
+ {"names", 1, VectorNamesOp, 2, 3, "?pattern?...",},
+};
+
+static int nCmdOps = sizeof(vectorCmdOps) / sizeof(Blt_OpSpec);
+
+/*ARGSUSED*/
+static int
+VectorCmd(
+ ClientData clientData, /* Interpreter-specific data. */
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ VectorCmdProc *proc;
+ /*
+ * Try to replicate the old vector command's behavior:
+ */
+ if (objc > 1) {
+ char *string;
+ char c;
+ int i;
+ Blt_OpSpec *specPtr;
+
+ string = Tcl_GetString(objv[1]);
+ c = string[0];
+ for (specPtr = vectorCmdOps, i = 0; i < nCmdOps; i++, specPtr++) {
+ if ((c == specPtr->name[0]) &&
+ (strcmp(string, specPtr->name) == 0)) {
+ goto doOp;
+ }
+ }
+ /*
+ * The first argument is not an operation, so assume that its
+ * actually the name of a vector to be created
+ */
+ return VectorCreate2(clientData, interp, 1, objc, objv);
+ }
+ doOp:
+ /* Do the usual vector operation lookup now. */
+ proc = Blt_GetOpFromObj(interp, nCmdOps, vectorCmdOps, BLT_OP_ARG1,
+ objc, objv,0);
+ if (proc == NULL) {
+ return TCL_ERROR;
+ }
+ return (*proc) (clientData, interp, objc, objv);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * VectorInterpDeleteProc --
+ *
+ * This is called when the interpreter hosting the "vector" command
+ * is deleted.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Destroys the math and index hash tables. In addition removes
+ * the hash table managing all vector names.
+ *
+ *---------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+VectorInterpDeleteProc(
+ ClientData clientData, /* Interpreter-specific data. */
+ Tcl_Interp *interp)
+{
+ VectorInterpData *dataPtr = clientData;
+ Blt_HashEntry *hPtr;
+ Blt_HashSearch cursor;
+
+ for (hPtr = Blt_FirstHashEntry(&dataPtr->vectorTable, &cursor);
+ hPtr != NULL; hPtr = Blt_NextHashEntry(&cursor)) {
+ Vector *vPtr;
+
+ vPtr = Blt_GetHashValue(hPtr);
+ vPtr->hashPtr = NULL;
+ Blt_Vec_Free(vPtr);
+ }
+ Blt_DeleteHashTable(&dataPtr->vectorTable);
+
+ /* If any user-defined math functions were installed, remove them. */
+ Blt_Vec_UninstallMathFunctions(&dataPtr->mathProcTable);
+ Blt_DeleteHashTable(&dataPtr->mathProcTable);
+
+ Blt_DeleteHashTable(&dataPtr->indexProcTable);
+ Tcl_DeleteAssocData(interp, VECTOR_THREAD_KEY);
+ free(dataPtr);
+}
+
+VectorInterpData *
+Blt_Vec_GetInterpData(Tcl_Interp *interp)
+{
+ VectorInterpData *dataPtr;
+ Tcl_InterpDeleteProc *proc;
+
+ dataPtr = (VectorInterpData *)
+ Tcl_GetAssocData(interp, VECTOR_THREAD_KEY, &proc);
+ if (dataPtr == NULL) {
+ dataPtr = malloc(sizeof(VectorInterpData));
+ dataPtr->interp = interp;
+ dataPtr->nextId = 0;
+ Tcl_SetAssocData(interp, VECTOR_THREAD_KEY, VectorInterpDeleteProc,
+ dataPtr);
+ Blt_InitHashTable(&dataPtr->vectorTable, BLT_STRING_KEYS);
+ Blt_InitHashTable(&dataPtr->mathProcTable, BLT_STRING_KEYS);
+ Blt_InitHashTable(&dataPtr->indexProcTable, BLT_STRING_KEYS);
+ Blt_Vec_InstallMathFunctions(&dataPtr->mathProcTable);
+ Blt_Vec_InstallSpecialIndices(&dataPtr->indexProcTable);
+ srand48(time((time_t *) NULL));
+ }
+ return dataPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_VectorCmdInitProc --
+ *
+ * This procedure is invoked to initialize the "vector" command.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Creates the new command and adds a new entry into a global Tcl
+ * associative array.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Blt_VectorCmdInitProc(Tcl_Interp *interp)
+{
+ static Blt_InitCmdSpec cmdSpec = {"vector", VectorCmd, };
+
+ cmdSpec.clientData = Blt_Vec_GetInterpData(interp);
+ return Blt_InitCmd(interp, "::blt", &cmdSpec);
+}
+
+
+
+/* C Application interface to vectors */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_CreateVector --
+ *
+ * Creates a new vector by the name and size.
+ *
+ * Results:
+ * A standard TCL result. If the new array size is invalid or a vector
+ * already exists by that name, TCL_ERROR is returned. Otherwise TCL_OK
+ * is returned and the new vector is created.
+ *
+ * Side Effects:
+ * Memory will be allocated for the new vector. A new TCL command and
+ * Tcl array variable will be created.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+/*LINTLIBRARY*/
+int
+Blt_CreateVector2(
+ Tcl_Interp *interp,
+ const char *vecName, const char *cmdName, const char *varName,
+ int initialSize,
+ Blt_Vector **vecPtrPtr)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr;
+ int isNew;
+ char *nameCopy;
+
+ if (initialSize < 0) {
+ Tcl_AppendResult(interp, "bad vector size \"", Blt_Itoa(initialSize),
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ dataPtr = Blt_Vec_GetInterpData(interp);
+
+ nameCopy = Blt_Strdup(vecName);
+ vPtr = Blt_Vec_Create(dataPtr, nameCopy, cmdName, varName, &isNew);
+ free(nameCopy);
+
+ if (vPtr == NULL) {
+ return TCL_ERROR;
+ }
+ if (initialSize > 0) {
+ if (Blt_Vec_ChangeLength(interp, vPtr, initialSize) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (vecPtrPtr != NULL) {
+ *vecPtrPtr = (Blt_Vector *) vPtr;
+ }
+ return TCL_OK;
+}
+
+int
+Blt_CreateVector(
+ Tcl_Interp *interp,
+ const char *name,
+ int size,
+ Blt_Vector **vecPtrPtr)
+{
+ return Blt_CreateVector2(interp, name, name, name, size, vecPtrPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DeleteVector --
+ *
+ * Deletes the vector of the given name. All clients with designated
+ * callback routines will be notified.
+ *
+ * Results:
+ * A standard TCL result. If no vector exists by that name, TCL_ERROR is
+ * returned. Otherwise TCL_OK is returned and vector is deleted.
+ *
+ * Side Effects:
+ * Memory will be released for the new vector. Both the TCL command and
+ * array variable will be deleted. All clients which set call back
+ * procedures will be notified.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+int
+Blt_DeleteVector(Blt_Vector *vecPtr)
+{
+ Vector *vPtr = (Vector *)vecPtr;
+
+ Blt_Vec_Free(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_DeleteVectorByName --
+ *
+ * Deletes the vector of the given name. All clients with designated
+ * callback routines will be notified.
+ *
+ * Results:
+ * A standard TCL result. If no vector exists by that name, TCL_ERROR is
+ * returned. Otherwise TCL_OK is returned and vector is deleted.
+ *
+ * Side Effects:
+ * Memory will be released for the new vector. Both the TCL command and
+ * array variable will be deleted. All clients which set call back
+ * procedures will be notified.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*LINTLIBRARY*/
+int
+Blt_DeleteVectorByName(Tcl_Interp *interp, const char *name)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr;
+ char *nameCopy;
+ int result;
+
+ /*
+ * If the vector name was passed via a read-only string (e.g. "x"), the
+ * Blt_Vec_ParseElement routine will segfault when it tries to write into
+ * the string. Therefore make a writable copy and free it when we're
+ * done.
+ */
+ nameCopy = Blt_Strdup(name);
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ result = Blt_Vec_LookupName(dataPtr, nameCopy, &vPtr);
+ free(nameCopy);
+
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_Vec_Free(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_VectorExists2 --
+ *
+ * Returns whether the vector associated with the client token still
+ * exists.
+ *
+ * Results:
+ * Returns 1 is the vector still exists, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_VectorExists2(Tcl_Interp *interp, const char *vecName)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ if (GetVectorObject(dataPtr, vecName, NS_SEARCH_BOTH) != NULL) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_VectorExists --
+ *
+ * Returns whether the vector associated with the client token
+ * still exists.
+ *
+ * Results:
+ * Returns 1 is the vector still exists, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_VectorExists(Tcl_Interp *interp, const char *vecName)
+{
+ char *nameCopy;
+ int result;
+
+ /*
+ * If the vector name was passed via a read-only string (e.g. "x"), the
+ * Blt_VectorParseName routine will segfault when it tries to write into
+ * the string. Therefore make a writable copy and free it when we're
+ * done.
+ */
+ nameCopy = Blt_Strdup(vecName);
+ result = Blt_VectorExists2(interp, nameCopy);
+ free(nameCopy);
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetVector --
+ *
+ * Returns a pointer to the vector associated with the given name.
+ *
+ * Results:
+ * A standard TCL result. If there is no vector "name", TCL_ERROR is
+ * returned. Otherwise TCL_OK is returned and vecPtrPtr will point to
+ * the vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetVector(Tcl_Interp *interp, const char *name, Blt_Vector **vecPtrPtr)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr;
+ char *nameCopy;
+ int result;
+
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ /*
+ * If the vector name was passed via a read-only string (e.g. "x"), the
+ * Blt_VectorParseName routine will segfault when it tries to write into
+ * the string. Therefore make a writable copy and free it when we're
+ * done.
+ */
+ nameCopy = Blt_Strdup(name);
+ result = Blt_Vec_LookupName(dataPtr, nameCopy, &vPtr);
+ free(nameCopy);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_Vec_UpdateRange(vPtr);
+ *vecPtrPtr = (Blt_Vector *) vPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetVectorFromObj --
+ *
+ * Returns a pointer to the vector associated with the given name.
+ *
+ * Results:
+ * A standard TCL result. If there is no vector "name", TCL_ERROR
+ * is returned. Otherwise TCL_OK is returned and vecPtrPtr will
+ * point to the vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetVectorFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Blt_Vector **vecPtrPtr)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr;
+
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ if (Blt_Vec_LookupName(dataPtr, Tcl_GetString(objPtr), &vPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Blt_Vec_UpdateRange(vPtr);
+ *vecPtrPtr = (Blt_Vector *) vPtr;
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ResetVector --
+ *
+ * Resets the vector data. This is called by a client to indicate that
+ * the vector data has changed. The vector does not need to point to
+ * different memory. Any clients of the vector will be notified of the
+ * change.
+ *
+ * Results:
+ * A standard TCL result. If the new array size is invalid,
+ * TCL_ERROR is returned. Otherwise TCL_OK is returned and the
+ * new vector data is recorded.
+ *
+ * Side Effects:
+ * Any client designated callbacks will be posted. Memory may
+ * be changed for the vector array.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ResetVector(
+ Blt_Vector *vecPtr,
+ double *valueArr, /* Array containing the elements of the
+ * vector. If NULL, indicates to reset the
+ * vector.*/
+ int length, /* The number of elements that the vector
+ * currently holds. */
+ int size, /* The maximum number of elements that the
+ * array can hold. */
+ Tcl_FreeProc *freeProc) /* Address of memory deallocation routine
+ * for the array of values. Can also be
+ * TCL_STATIC, TCL_DYNAMIC, or TCL_VOLATILE. */
+{
+ Vector *vPtr = (Vector *)vecPtr;
+
+ if (size < 0) {
+ Tcl_AppendResult(vPtr->interp, "bad array size", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return Blt_Vec_Reset(vPtr, valueArr, length, size, freeProc);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ResizeVector --
+ *
+ * Changes the size of the vector. All clients with designated callback
+ * routines will be notified of the size change.
+ *
+ * Results:
+ * A standard TCL result. If no vector exists by that name, TCL_ERROR is
+ * returned. Otherwise TCL_OK is returned and vector is resized.
+ *
+ * Side Effects:
+ * Memory may be reallocated for the new vector size. All clients which
+ * set call back procedures will be notified.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ResizeVector(Blt_Vector *vecPtr, int length)
+{
+ Vector *vPtr = (Vector *)vecPtr;
+
+ if (Blt_Vec_ChangeLength((Tcl_Interp *)NULL, vPtr, length) != TCL_OK) {
+ Tcl_AppendResult(vPtr->interp, "can't resize vector \"", vPtr->name,
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (vPtr->flush) {
+ Blt_Vec_FlushCache(vPtr);
+ }
+ Blt_Vec_UpdateClients(vPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_AllocVectorId --
+ *
+ * Creates an identifier token for an existing vector. The identifier is
+ * used by the client routines to get call backs when (and if) the vector
+ * changes.
+ *
+ * Results:
+ * A standard TCL result. If "vecName" is not associated with a vector,
+ * TCL_ERROR is returned and interp->result is filled with an error
+ * message.
+ *
+ *---------------------------------------------------------------------------
+ */
+Blt_VectorId
+Blt_AllocVectorId(Tcl_Interp *interp, const char *name)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Vector *vPtr;
+ VectorClient *clientPtr;
+ Blt_VectorId clientId;
+ int result;
+ char *nameCopy;
+
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ /*
+ * If the vector name was passed via a read-only string (e.g. "x"), the
+ * Blt_VectorParseName routine will segfault when it tries to write into
+ * the string. Therefore make a writable copy and free it when we're
+ * done.
+ */
+ nameCopy = Blt_Strdup(name);
+ result = Blt_Vec_LookupName(dataPtr, nameCopy, &vPtr);
+ free(nameCopy);
+
+ if (result != TCL_OK) {
+ return (Blt_VectorId) 0;
+ }
+ /* Allocate a new client structure */
+ clientPtr = calloc(1, sizeof(VectorClient));
+ clientPtr->magic = VECTOR_MAGIC;
+
+ /* Add the new client to the server's list of clients */
+ clientPtr->link = Blt_Chain_Append(vPtr->chain, clientPtr);
+ clientPtr->serverPtr = vPtr;
+ clientId = (Blt_VectorId) clientPtr;
+ return clientId;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_SetVectorChangedProc --
+ *
+ * Sets the routine to be called back when the vector is changed or
+ * deleted. *clientData* will be provided as an argument. If *proc* is
+ * NULL, no callback will be made.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * The designated routine will be called when the vector is changed
+ * or deleted.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_SetVectorChangedProc(
+ Blt_VectorId clientId, /* Client token identifying the vector */
+ Blt_VectorChangedProc *proc,/* Address of routine to call when the contents
+ * of the vector change. If NULL, no routine
+ * will be called */
+ ClientData clientData) /* One word of information to pass along when
+ * the above routine is called */
+{
+ VectorClient *clientPtr = (VectorClient *)clientId;
+
+ if (clientPtr->magic != VECTOR_MAGIC) {
+ return; /* Not a valid token */
+ }
+ clientPtr->clientData = clientData;
+ clientPtr->proc = proc;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeVectorId --
+ *
+ * Releases the token for an existing vector. This indicates that the
+ * client is no longer interested the vector. Any previously specified
+ * callback routine will no longer be invoked when (and if) the vector
+ * changes.
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Any previously specified callback routine will no longer be
+ * invoked when (and if) the vector changes.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FreeVectorId(Blt_VectorId clientId)
+{
+ VectorClient *clientPtr = (VectorClient *)clientId;
+
+ if (clientPtr->magic != VECTOR_MAGIC) {
+ return; /* Not a valid token */
+ }
+ if (clientPtr->serverPtr != NULL) {
+ /* Remove the client from the server's list */
+ Blt_Chain_DeleteLink(clientPtr->serverPtr->chain, clientPtr->link);
+ }
+ free(clientPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NameOfVectorId --
+ *
+ * Returns the name of the vector (and array variable).
+ *
+ * Results:
+ * The name of the array variable is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_NameOfVectorId(Blt_VectorId clientId)
+{
+ VectorClient *clientPtr = (VectorClient *)clientId;
+
+ if ((clientPtr->magic != VECTOR_MAGIC) || (clientPtr->serverPtr == NULL)) {
+ return NULL;
+ }
+ return clientPtr->serverPtr->name;
+}
+
+const char *
+Blt_NameOfVector(Blt_Vector *vecPtr) /* Vector to query. */
+{
+ Vector *vPtr = (Vector *)vecPtr;
+ return vPtr->name;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_VectorNotifyPending --
+ *
+ * Returns the name of the vector (and array variable).
+ *
+ * Results:
+ * The name of the array variable is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_VectorNotifyPending(Blt_VectorId clientId)
+{
+ VectorClient *clientPtr = (VectorClient *)clientId;
+
+ if ((clientPtr == NULL) || (clientPtr->magic != VECTOR_MAGIC) ||
+ (clientPtr->serverPtr == NULL)) {
+ return 0;
+ }
+ return (clientPtr->serverPtr->notifyFlags & NOTIFY_PENDING);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetVectorById --
+ *
+ * Returns a pointer to the vector associated with the client
+ * token.
+ *
+ * Results:
+ * A standard TCL result. If the client token is not associated
+ * with a vector any longer, TCL_ERROR is returned. Otherwise,
+ * TCL_OK is returned and vecPtrPtr will point to vector.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetVectorById(
+ Tcl_Interp *interp,
+ Blt_VectorId clientId, /* Client token identifying the vector */
+ Blt_Vector **vecPtrPtr)
+{
+ VectorClient *clientPtr = (VectorClient *)clientId;
+
+ if (clientPtr->magic != VECTOR_MAGIC) {
+ Tcl_AppendResult(interp, "bad vector token", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (clientPtr->serverPtr == NULL) {
+ Tcl_AppendResult(interp, "vector no longer exists", (char *)NULL);
+ return TCL_ERROR;
+ }
+ Blt_Vec_UpdateRange(clientPtr->serverPtr);
+ *vecPtrPtr = (Blt_Vector *) clientPtr->serverPtr;
+ return TCL_OK;
+}
+
+/*LINTLIBRARY*/
+void
+Blt_InstallIndexProc(Tcl_Interp *interp, const char *string,
+ Blt_VectorIndexProc *procPtr)
+{
+ VectorInterpData *dataPtr; /* Interpreter-specific data. */
+ Blt_HashEntry *hPtr;
+ int isNew;
+
+ dataPtr = Blt_Vec_GetInterpData(interp);
+ hPtr = Blt_CreateHashEntry(&dataPtr->indexProcTable, string, &isNew);
+ if (procPtr == NULL) {
+ Blt_DeleteHashEntry(&dataPtr->indexProcTable, hPtr);
+ } else {
+ Blt_SetHashValue(hPtr, procPtr);
+ }
+}
+
+/* spinellia at acm.org START */
+
+
+#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr
+
+/* routine by Brenner
+ * data is the array of complex data points, perversely
+ * starting at 1
+ * nn is the number of complex points, i.e. half the length of data
+ * isign is 1 for forward, -1 for inverse
+ */
+static void
+four1(double *data, unsigned long nn, int isign)
+{
+ unsigned long n,mmax,m,j,istep,i;
+ double wtemp,wr,wpr,wpi,wi,theta;
+ double tempr,tempi;
+
+ n=nn << 1;
+ j=1;
+ for (i = 1;i<n;i+=2) {
+ if (j > i) {
+ SWAP(data[j],data[i]);
+ SWAP(data[j+1],data[i+1]);
+ }
+ m=n >> 1;
+ while (m >= 2 && j > m) {
+ j -= m;
+ m >>= 1;
+ }
+ j += m;
+ }
+ mmax=2;
+ while (n > mmax) {
+ istep=mmax << 1;
+ theta=isign*(6.28318530717959/mmax);
+ wtemp=sin(0.5*theta);
+ wpr = -2.0*wtemp*wtemp;
+ wpi=sin(theta);
+ wr=1.0;
+ wi=0.0;
+ for (m=1;m<mmax;m+=2) {
+ for (i=m;i<=n;i+=istep) {
+ j=i+mmax;
+ tempr=wr*data[j]-wi*data[j+1];
+ tempi=wr*data[j+1]+wi*data[j];
+ data[j]=data[i]-tempr;
+ data[j+1]=data[i+1]-tempi;
+ data[i] += tempr;
+ data[i+1] += tempi;
+ }
+ wr=(wtemp=wr)*wpr-wi*wpi+wr;
+ wi=wi*wpr+wtemp*wpi+wi;
+ }
+ mmax=istep;
+ }
+}
+#undef SWAP
+
+static int
+smallest_power_of_2_not_less_than(int x)
+{
+ int pow2 = 1;
+
+ while (pow2 < x){
+ pow2 <<= 1;
+ }
+ return pow2;
+}
+
+
+int
+Blt_Vec_FFT(
+ Tcl_Interp *interp, /* Interpreter to report errors to */
+ Vector *realPtr, /* If non-NULL, indicates to compute and
+ store the real values in this vector. */
+ Vector *phasesPtr, /* If non-NULL, indicates to compute
+ * and store the imaginary values in
+ * this vector. */
+ Vector *freqPtr, /* If non-NULL, indicates to compute
+ * and store the frequency values in
+ * this vector. */
+ double delta, /* */
+ int flags, /* Bit mask representing various
+ * flags: FFT_NO_constANT,
+ * FFT_SPECTRUM, and FFT_BARTLETT. */
+ Vector *srcPtr)
+{
+ int length;
+ int pow2len;
+ double *paddedData;
+ int i;
+ double Wss = 0.0;
+ /* TENTATIVE */
+ int middle = 1;
+ int noconstant;
+
+ noconstant = (flags & FFT_NO_CONSTANT) ? 1 : 0;
+
+ /* Length of the original vector. */
+ length = srcPtr->last - srcPtr->first + 1;
+ /* new length */
+ pow2len = smallest_power_of_2_not_less_than( length );
+
+ /* We do not do in-place FFTs */
+ if (realPtr == srcPtr) {
+ Tcl_AppendResult(interp, "real vector \"", realPtr->name,
+ "\" can't be the same as the source", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (phasesPtr != NULL) {
+ if (phasesPtr == srcPtr) {
+ Tcl_AppendResult(interp, "imaginary vector \"", phasesPtr->name,
+ "\" can't be the same as the source", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_ChangeLength(interp, phasesPtr,
+ pow2len/2-noconstant+middle) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (freqPtr != NULL) {
+ if (freqPtr == srcPtr) {
+ Tcl_AppendResult(interp, "frequency vector \"", freqPtr->name,
+ "\" can't be the same as the source", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_ChangeLength(interp, freqPtr,
+ pow2len/2-noconstant+middle) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /* Allocate memory zero-filled array. */
+ paddedData = calloc(pow2len * 2, sizeof(double));
+ if (paddedData == NULL) {
+ Tcl_AppendResult(interp, "can't allocate memory for padded data",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Since we just do real transforms, only even locations will be
+ * filled with data.
+ */
+ if (flags & FFT_BARTLETT) { /* Bartlett window 1 - ( (x - N/2) / (N/2) ) */
+ double Nhalf = pow2len*0.5;
+ double Nhalf_1 = 1.0 / Nhalf;
+ double w;
+
+ for (i = 0; i < length; i++) {
+ w = 1.0 - fabs( (i-Nhalf) * Nhalf_1 );
+ Wss += w;
+ paddedData[2*i] = w * srcPtr->valueArr[i];
+ }
+ for(/*empty*/; i < pow2len; i++) {
+ w = 1.0 - fabs((i-Nhalf) * Nhalf_1);
+ Wss += w;
+ }
+ } else { /* Squared window, i.e. no data windowing. */
+ for (i = 0; i < length; i++) {
+ paddedData[2*i] = srcPtr->valueArr[i];
+ }
+ Wss = pow2len;
+ }
+
+ /* Fourier */
+ four1(paddedData-1, pow2len, 1);
+
+ /*
+ for(i=0;i<pow2len;i++){
+ printf( "(%f %f) ", paddedData[2*i], paddedData[2*i+1] );
+ }
+ */
+
+ /* the spectrum is the modulus of the transforms, scaled by 1/N^2 */
+ /* or 1/(N * Wss) for windowed data */
+ if (flags & FFT_SPECTRUM) {
+ double re, im, reS, imS;
+ double factor = 1.0 / (pow2len*Wss);
+ double *v = realPtr->valueArr;
+
+ for (i = 0 + noconstant; i < pow2len / 2; i++) {
+ re = paddedData[2*i];
+ im = paddedData[2*i+1];
+ reS = paddedData[2*pow2len-2*i-2];
+ imS = paddedData[2*pow2len-2*i-1];
+ v[i - noconstant] = factor * (
+# if 0
+ hypot( paddedData[2*i], paddedData[2*i+1] )
+ + hypot(
+ paddedData[pow2len*2-2*i-2],
+ paddedData[pow2len*2-2*i-1]
+ )
+# else
+ sqrt( re*re + im* im ) + sqrt( reS*reS + imS*imS )
+# endif
+ );
+ }
+ } else {
+ for(i = 0 + noconstant; i < pow2len / 2 + middle; i++) {
+ realPtr->valueArr[i - noconstant] = paddedData[2*i];
+ }
+ }
+ if( phasesPtr != NULL ){
+ for (i = 0 + noconstant; i < pow2len / 2 + middle; i++) {
+ phasesPtr->valueArr[i-noconstant] = paddedData[2*i+1];
+ }
+ }
+
+ /* Compute frequencies */
+ if (freqPtr != NULL) {
+ double N = pow2len;
+ double denom = 1.0 / N / delta;
+ for( i=0+noconstant; i<pow2len/2+middle; i++ ){
+ freqPtr->valueArr[i-noconstant] = ((double) i) * denom;
+ }
+ }
+
+ /* Memory is necessarily dynamic, because nobody touched it ! */
+ free(paddedData);
+
+ realPtr->offset = 0;
+ return TCL_OK;
+}
+
+
+int
+Blt_Vec_InverseFFT(Tcl_Interp *interp, Vector *srcImagPtr, Vector *destRealPtr,
+ Vector *destImagPtr, Vector *srcPtr)
+{
+ int length;
+ int pow2len;
+ double *paddedData;
+ int i;
+ double oneOverN;
+
+ if ((destRealPtr == srcPtr) || (destImagPtr == srcPtr )){
+/* we do not do in-place FFTs */
+ return TCL_ERROR;
+ }
+ length = srcPtr->last - srcPtr->first + 1;
+
+/* minus one because of the magical middle element! */
+ pow2len = smallest_power_of_2_not_less_than( (length-1)*2 );
+ oneOverN = 1.0 / pow2len;
+
+ if (Blt_Vec_ChangeLength(interp, destRealPtr, pow2len) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Blt_Vec_ChangeLength(interp, destImagPtr, pow2len) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if( length != (srcImagPtr->last - srcImagPtr->first + 1) ){
+ Tcl_AppendResult(srcPtr->interp,
+ "the length of the imagPart vector must ",
+ "be the same as the real one", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ paddedData = malloc( pow2len*2*sizeof(double) );
+ if( paddedData == NULL ){
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "memory allocation failed", (char *)NULL);
+ }
+ return TCL_ERROR;
+ }
+ for(i=0;i<pow2len*2;i++) { paddedData[i] = 0.0; }
+ for(i=0;i<length-1;i++){
+ paddedData[2*i] = srcPtr->valueArr[i];
+ paddedData[2*i+1] = srcImagPtr->valueArr[i];
+ paddedData[pow2len*2 - 2*i - 2 ] = srcPtr->valueArr[i+1];
+ paddedData[pow2len*2 - 2*i - 1 ] = - srcImagPtr->valueArr[i+1];
+ }
+/* mythical middle element */
+ paddedData[(length-1)*2] = srcPtr->valueArr[length-1];
+ paddedData[(length-1)*2+1] = srcImagPtr->valueArr[length-1];
+
+/*
+for(i=0;i<pow2len;i++){
+ printf( "(%f %f) ", paddedData[2*i], paddedData[2*i+1] );
+}
+ */
+
+/* fourier */
+ four1( paddedData-1, pow2len, -1 );
+
+/* put values in their places, normalising by 1/N */
+ for(i=0;i<pow2len;i++){
+ destRealPtr->valueArr[i] = paddedData[2*i] * oneOverN;
+ destImagPtr->valueArr[i] = paddedData[2*i+1] * oneOverN;
+ }
+
+/* memory is necessarily dynamic, because nobody touched it ! */
+ free( paddedData );
+
+ return TCL_OK;
+}
+
+
+/* spinellia at acm.org STOP */
+
+
+
+static double
+FindSplit(Point2d *points, int i, int j, int *split)
+{
+ double maxDist2;
+
+ maxDist2 = -1.0;
+ if ((i + 1) < j) {
+ int k;
+ double a, b, c;
+
+ /*
+ *
+ * dist2 P(k) = | 1 P(i).x P(i).y |
+ * | 1 P(j).x P(j).y |
+ * | 1 P(k).x P(k).y |
+ * ------------------------------------------
+ * (P(i).x - P(j).x)^2 + (P(i).y - P(j).y)^2
+ */
+
+ a = points[i].y - points[j].y;
+ b = points[j].x - points[i].x;
+ c = (points[i].x * points[j].y) - (points[i].y * points[j].x);
+ for (k = (i + 1); k < j; k++) {
+ double dist2;
+
+ dist2 = (points[k].x * a) + (points[k].y * b) + c;
+ if (dist2 < 0.0) {
+ dist2 = -dist2;
+ }
+ if (dist2 > maxDist2) {
+ maxDist2 = dist2; /* Track the maximum. */
+ *split = k;
+ }
+ }
+ /* Correction for segment length---should be redone if can == 0 */
+ maxDist2 *= maxDist2 / (a * a + b * b);
+ }
+ return maxDist2;
+}
+
+
+/* Douglas-Peucker line simplification algorithm */
+int
+Blt_SimplifyLine(Point2d *inputPts, int low, int high, double tolerance,
+ int *indices)
+{
+#define StackPush(a) s++, stack[s] = (a)
+#define StackPop(a) (a) = stack[s], s--
+#define StackEmpty() (s < 0)
+#define StackTop() stack[s]
+ int *stack;
+ int split = -1;
+ double dist2, tolerance2;
+ int s = -1; /* Points to top stack item. */
+ int count;
+
+ stack = malloc(sizeof(int) * (high - low + 1));
+ StackPush(high);
+ count = 0;
+ indices[count++] = 0;
+ tolerance2 = tolerance * tolerance;
+ while (!StackEmpty()) {
+ dist2 = FindSplit(inputPts, low, StackTop(), &split);
+ if (dist2 > tolerance2) {
+ StackPush(split);
+ } else {
+ indices[count++] = StackTop();
+ StackPop(low);
+ }
+ }
+ free(stack);
+ return count;
+}
diff --git a/tlt3.0/bltVector.h b/tlt3.0/bltVector.h
new file mode 100644
index 0000000..2ec03bc
--- /dev/null
+++ b/tlt3.0/bltVector.h
@@ -0,0 +1,137 @@
+
+/*
+ * bltVector.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_VECTOR_H
+#define _BLT_VECTOR_H
+
+typedef enum {
+ BLT_VECTOR_NOTIFY_UPDATE = 1, /* The vector's values has been updated */
+ BLT_VECTOR_NOTIFY_DESTROY /* The vector has been destroyed and the client
+ * should no longer use its data (calling
+ * Blt_FreeVectorId) */
+} Blt_VectorNotify;
+
+typedef struct _Blt_VectorId *Blt_VectorId;
+
+typedef void (Blt_VectorChangedProc)(Tcl_Interp *interp, ClientData clientData,
+ Blt_VectorNotify notify);
+
+typedef struct {
+ double *valueArr; /* Array of values (possibly malloc-ed) */
+ int numValues; /* Number of values in the array */
+ int arraySize; /* Size of the allocated space */
+ double min, max; /* Minimum and maximum values in the vector */
+ int dirty; /* Indicates if the vector has been updated */
+ int reserved; /* Reserved for future use */
+
+} Blt_Vector;
+
+typedef double (Blt_VectorIndexProc)(Blt_Vector * vecPtr);
+
+typedef enum {
+ BLT_MATH_FUNC_SCALAR = 1, /* The function returns a single double
+ * precision value. */
+ BLT_MATH_FUNC_VECTOR /* The function processes the entire vector. */
+} Blt_MathFuncType;
+
+/*
+ * To be safe, use the macros below, rather than the fields of the
+ * structure directly.
+ *
+ * The Blt_Vector is basically an opaque type. But it's also the
+ * actual memory address of the vector itself. I wanted to make the
+ * API as unobtrusive as possible. So instead of giving you a copy of
+ * the vector, providing various functions to access and update the
+ * vector, you get your hands on the actual memory (array of doubles)
+ * shared by all the vector's clients.
+ *
+ * The trade-off for speed and convenience is safety. You can easily
+ * break things by writing into the vector when other clients are
+ * using it. Use Blt_ResetVector to get around this. At least the
+ * macros are a reminder it isn't really safe to reset the data
+ * fields, except by the API routines.
+ */
+#define Blt_VecData(v) ((v)->valueArr)
+#define Blt_VecLength(v) ((v)->numValues)
+#define Blt_VecSize(v) ((v)->arraySize)
+#define Blt_VecDirty(v) ((v)->dirty)
+
+extern double Blt_VecMin(Blt_Vector *vPtr);
+extern double Blt_VecMax(Blt_Vector *vPtr);
+
+extern Blt_VectorId Blt_AllocVectorId(Tcl_Interp *interp,
+ const char *vecName);
+
+extern void Blt_SetVectorChangedProc(Blt_VectorId clientId,
+ Blt_VectorChangedProc *proc, ClientData clientData);
+
+extern void Blt_FreeVectorId(Blt_VectorId clientId);
+
+extern int Blt_GetVectorById(Tcl_Interp *interp, Blt_VectorId clientId,
+ Blt_Vector **vecPtrPtr);
+
+extern const char *Blt_NameOfVectorId(Blt_VectorId clientId);
+
+extern const char *Blt_NameOfVector(Blt_Vector *vecPtr);
+
+extern int Blt_VectorNotifyPending(Blt_VectorId clientId);
+
+extern int Blt_CreateVector(Tcl_Interp *interp, const char *vecName,
+ int size, Blt_Vector ** vecPtrPtr);
+
+extern int Blt_CreateVector2(Tcl_Interp *interp, const char *vecName,
+ const char *cmdName, const char *varName, int initialSize,
+ Blt_Vector **vecPtrPtr);
+
+extern int Blt_GetVector(Tcl_Interp *interp, const char *vecName,
+ Blt_Vector **vecPtrPtr);
+
+extern int Blt_GetVectorFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Blt_Vector **vecPtrPtr);
+
+extern int Blt_VectorExists(Tcl_Interp *interp, const char *vecName);
+
+extern int Blt_ResetVector(Blt_Vector *vecPtr, double *dataArr, int n,
+ int arraySize, Tcl_FreeProc *freeProc);
+
+extern int Blt_ResizeVector(Blt_Vector *vecPtr, int n);
+
+extern int Blt_DeleteVectorByName(Tcl_Interp *interp, const char *vecName);
+
+extern int Blt_DeleteVector(Blt_Vector *vecPtr);
+
+extern int Blt_ExprVector(Tcl_Interp *interp, char *expr,
+ Blt_Vector *vecPtr);
+
+extern void Blt_InstallIndexProc(Tcl_Interp *interp, const char *indexName,
+ Blt_VectorIndexProc * procPtr);
+
+extern int Blt_VectorExists2(Tcl_Interp *interp, const char *vecName);
+
+#endif /* _BLT_VECTOR_H */
diff --git a/tlt3.0/bltWindow.c b/tlt3.0/bltWindow.c
new file mode 100644
index 0000000..be0255b
--- /dev/null
+++ b/tlt3.0/bltWindow.c
@@ -0,0 +1,247 @@
+/*
+ * bltWindow.c --
+ *
+ * This module implements additional window functions for the BLT
+ * toolkit.
+ *
+ * Copyright 1991-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+
+#include <tkPort.h>
+#include <tkInt.h>
+
+#include "bltInt.h"
+#include "bltWindow.h"
+#include "bltHash.h"
+
+/*
+ * Cache drawable information.
+ *
+ * There are specific times when we need information about the drawable
+ * that is not available via the normal argument passing. For example,
+ * XFT font rendering requires that the correct depth XftDraw be used.
+ * If we create a painter from a drawable, we need to know its depth,
+ * colormap, and visual also.
+ *
+ * We can usually get this information using XGetWindowAttributes at
+ * the cost of a round-trip to the X server. Instead we'll cache it
+ * in a hash table. We don't have to cache every window. We need to
+ * watch destroy events and freeing pixmaps.
+ */
+
+typedef struct {
+ Display *display;
+ Drawable drawable;
+} DrawableKey;
+
+static Blt_HashTable attribTable;
+static int initialized = FALSE;
+
+Blt_DrawableAttributes* Blt_GetDrawableAttribs(Display *display,
+ Drawable drawable)
+{
+ if (drawable != None) {
+ Blt_HashEntry *hPtr;
+ DrawableKey key;
+
+ if (!initialized) {
+ Blt_InitHashTable(&attribTable, sizeof(DrawableKey)/sizeof(int));
+ initialized = TRUE;
+ }
+ memset(&key, 0, sizeof(key));
+ key.drawable = drawable;
+ key.display = display;
+ hPtr = Blt_FindHashEntry(&attribTable, &key);
+ if (hPtr != NULL) {
+ return Blt_GetHashValue(hPtr);
+ }
+ }
+ return NULL; /* Don't have any information about this
+ * drawable. */
+}
+
+void Blt_SetDrawableAttribs(Display *display, Drawable drawable, int depth,
+ int width, int height, Colormap colormap,
+ Visual *visual)
+{
+ if (drawable != None) {
+ Blt_DrawableAttributes *attrPtr;
+ Blt_HashEntry *hPtr;
+ int isNew;
+ DrawableKey key;
+
+ if (!initialized) {
+ Blt_InitHashTable(&attribTable, sizeof(DrawableKey)/sizeof(int));
+ initialized = TRUE;
+ }
+ memset(&key, 0, sizeof(key));
+ key.drawable = drawable;
+ key.display = display;
+ hPtr = Blt_CreateHashEntry(&attribTable, &key, &isNew);
+ if (isNew) {
+ attrPtr = malloc(sizeof(Blt_DrawableAttributes));
+ Blt_SetHashValue(hPtr, attrPtr);
+ } else {
+ attrPtr = Blt_GetHashValue(hPtr);
+ }
+ /* Set or reset information for drawable. */
+ attrPtr->id = drawable;
+ attrPtr->depth = depth;
+ attrPtr->colormap = colormap;
+ attrPtr->visual = visual;
+ attrPtr->width = width;
+ attrPtr->height = height;
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FindChild --
+ *
+ * Performs a linear search for the named child window in a given
+ * parent window.
+ *
+ * This can be done via Tcl, but not through Tk's C API. It's
+ * simple enough, if you peek into the Tk_Window structure.
+ *
+ * Results:
+ * The child Tk_Window. If the named child can't be found, NULL
+ * is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Window Blt_FindChild(Tk_Window parent, char *name)
+{
+ TkWindow *winPtr;
+ TkWindow *parentPtr = (TkWindow *)parent;
+
+ for (winPtr = parentPtr->childList; winPtr != NULL;
+ winPtr = winPtr->nextPtr) {
+ if (strcmp(name, winPtr->nameUid) == 0) {
+ return (Tk_Window)winPtr;
+ }
+ }
+ return NULL;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FirstChildWindow --
+ *
+ * Performs a linear search for the named child window in a given
+ * parent window.
+ *
+ * This can be done via Tcl, but not through Tk's C API. It's
+ * simple enough, if you peek into the Tk_Window structure.
+ *
+ * Results:
+ * The child Tk_Window. If the named child can't be found, NULL
+ * is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Window Blt_FirstChild(Tk_Window parent)
+{
+ TkWindow *parentPtr = (TkWindow *)parent;
+ return (Tk_Window)parentPtr->childList;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FindChild --
+ *
+ * Performs a linear search for the named child window in a given
+ * parent window.
+ *
+ * This can be done via Tcl, but not through Tk's C API. It's
+ * simple enough, if you peek into the Tk_Window structure.
+ *
+ * Results:
+ * The child Tk_Window. If the named child can't be found, NULL
+ * is returned.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Window Blt_NextChild(Tk_Window tkwin)
+{
+ TkWindow *winPtr = (TkWindow *)tkwin;
+
+ if (winPtr == NULL) {
+ return NULL;
+ }
+ return (Tk_Window)winPtr->nextPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_Toplevel --
+ *
+ * Climbs up the widget hierarchy to find the top level window of
+ * the window given.
+ *
+ * Results:
+ * Returns the Tk_Window of the toplevel widget.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+Tk_Window Blt_Toplevel(Tk_Window tkwin)
+{
+ while (!Tk_IsTopLevel(tkwin)) {
+ tkwin = Tk_Parent(tkwin);
+ }
+ return tkwin;
+}
+
+void Blt_SetWindowInstanceData(Tk_Window tkwin, ClientData instanceData)
+{
+ TkWindow *winPtr = (TkWindow *)tkwin;
+
+ winPtr->instanceData = instanceData;
+}
+
+ClientData Blt_GetWindowInstanceData(Tk_Window tkwin)
+{
+ TkWindow *winPtr;
+
+ while (tkwin != NULL) {
+ winPtr = (TkWindow *)tkwin;
+ if (winPtr->instanceData != NULL) {
+ return (ClientData)winPtr->instanceData;
+ }
+ tkwin = Tk_Parent(tkwin);
+ }
+ return NULL;
+}
diff --git a/tlt3.0/bltWindow.h b/tlt3.0/bltWindow.h
new file mode 100644
index 0000000..503b4cf
--- /dev/null
+++ b/tlt3.0/bltWindow.h
@@ -0,0 +1,58 @@
+/*
+ * bltWindow.h --
+ *
+ * Copyright 1993-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _BLT_WINDOW_H
+#define _BLT_WINDOW_H
+
+#include <tk.h>
+
+typedef struct {
+ Drawable id;
+ unsigned short int width, height;
+ int depth;
+ Colormap colormap;
+ Visual *visual;
+} Blt_DrawableAttributes;
+
+extern Blt_DrawableAttributes *Blt_GetDrawableAttribs(Display *display,
+ Drawable drawable);
+
+extern void Blt_SetDrawableAttribs(Display *display, Drawable drawable,
+ int width, int height, int depth, Colormap colormap, Visual *visual);
+
+extern Tk_Window Blt_FindChild(Tk_Window parent, char *name);
+
+extern Tk_Window Blt_FirstChild(Tk_Window parent);
+
+extern Tk_Window Blt_NextChild(Tk_Window tkwin);
+
+extern Tk_Window Blt_Toplevel(Tk_Window tkwin);
+
+extern ClientData Blt_GetWindowInstanceData (Tk_Window tkwin);
+
+extern void Blt_SetWindowInstanceData (Tk_Window tkwin,
+ ClientData instanceData);
+
+#endif
diff --git a/tlt3.0/configure b/tlt3.0/configure
new file mode 100755
index 0000000..04e3aa3
--- /dev/null
+++ b/tlt3.0/configure
@@ -0,0 +1,10699 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for tlt 3.0.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 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
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # 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
+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+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+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
+test -x / || 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 :
+ export CONFIG_SHELL
+ # 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
+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+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+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 at 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_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_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; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # 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 -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+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
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# 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='tlt'
+PACKAGE_TARNAME='tlt'
+PACKAGE_VERSION='3.0'
+PACKAGE_STRING='tlt 3.0'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+# 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='LTLIBOBJS
+LIBOBJS
+TCLSH_PROG
+XFT_LIBS
+XFT_CFLAGS
+XMKMF
+VC_MANIFEST_EMBED_EXE
+VC_MANIFEST_EMBED_DLL
+RANLIB_STUB
+MAKE_STUB_LIB
+MAKE_STATIC_LIB
+MAKE_SHARED_LIB
+MAKE_LIB
+TCL_DBGX
+LDFLAGS_DEFAULT
+CFLAGS_DEFAULT
+LD_LIBRARY_PATH_VAR
+SHLIB_CFLAGS
+SHLIB_LD_LIBS
+SHLIB_LD
+STLIB_LD
+CFLAGS_WARNING
+CFLAGS_OPTIMIZE
+CFLAGS_DEBUG
+RC
+CELIB_DIR
+AR
+SHARED_BUILD
+TCL_THREADS
+TK_XLIB_DIR_NATIVE
+TK_TOP_DIR_NATIVE
+TK_INCLUDES
+TCL_TOP_DIR_NATIVE
+TCL_INCLUDES
+PKG_OBJECTS
+PKG_SOURCES
+MATH_LIBS
+EGREP
+GREP
+RANLIB
+SET_MAKE
+INSTALL
+CPP
+TK_XINCLUDES
+TK_LIBS
+TK_STUB_LIB_SPEC
+TK_STUB_LIB_FLAG
+TK_STUB_LIB_FILE
+TK_LIB_SPEC
+TK_LIB_FLAG
+TK_LIB_FILE
+TK_SRC_DIR
+TK_BIN_DIR
+TK_VERSION
+TCL_SHLIB_LD_LIBS
+TCL_LD_FLAGS
+TCL_EXTRA_CFLAGS
+TCL_DEFS
+TCL_LIBS
+CLEANFILES
+OBJEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+TCL_STUB_LIB_SPEC
+TCL_STUB_LIB_FLAG
+TCL_STUB_LIB_FILE
+TCL_LIB_SPEC
+TCL_LIB_FLAG
+TCL_LIB_FILE
+TCL_SRC_DIR
+TCL_BIN_DIR
+TCL_PATCH_LEVEL
+TCL_VERSION
+PKG_CFLAGS
+PKG_LIBS
+PKG_INCLUDES
+PKG_HEADERS
+PKG_TCL_SOURCES
+PKG_STUB_OBJECTS
+PKG_STUB_SOURCES
+PKG_STUB_LIB_FILE
+PKG_LIB_FILE
+EXEEXT
+CYGPATH
+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
+with_tcl
+with_tk
+with_tclinclude
+with_tkinclude
+enable_threads
+enable_shared
+enable_64bit
+enable_64bit_vis
+enable_rpath
+enable_wince
+with_celib
+enable_symbols
+with_x
+enable_xft
+'
+ 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_TARNAME}'
+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
+ 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 tlt 3.0 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/tlt]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+X features:
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of tlt 3.0:";;
+ esac
+ 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]
+ --enable-threads build with threads
+ --enable-shared build and link with shared libraries (default: on)
+ --enable-64bit enable 64bit support (default: off)
+ --enable-64bit-vis enable 64bit Sparc VIS support (default: off)
+ --disable-rpath disable rpath support (default: on)
+ --enable-wince enable Win/CE support (where applicable)
+ --enable-symbols build with debugging symbols (default: off)
+ --enable-xft use freetype/fontconfig/xft (default: on)
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-tcl directory containing tcl configuration
+ (tclConfig.sh)
+ --with-tk directory containing tk configuration (tkConfig.sh)
+ --with-tclinclude directory containing the public Tcl header files
+ --with-tkinclude directory containing the public Tk header files
+ --with-celib=DIR use Windows/CE support library from DIR
+ --with-x use the X Window System
+
+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
+tlt configure 3.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 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_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_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_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_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 ||
+ 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_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 tlt $as_me 3.0, which was
+generated by GNU Autoconf 2.69. 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
+
+
+
+#--------------------------------------------------------------------
+# Call TEA_INIT as the first TEA_ macro to set up initial vars.
+# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
+# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
+#--------------------------------------------------------------------
+
+
+ # TEA extensions pass this us the version of TEA they think they
+ # are compatible with.
+ TEA_VERSION="3.9"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct TEA configuration" >&5
+$as_echo_n "checking for correct TEA configuration... " >&6; }
+ if test x"${PACKAGE_NAME}" = x ; then
+ as_fn_error $? "
+The PACKAGE_NAME variable must be defined by your TEA configure.in" "$LINENO" 5
+ fi
+ if test x"3.9" = x ; then
+ as_fn_error $? "
+TEA version not specified." "$LINENO" 5
+ elif test "3.9" != "${TEA_VERSION}" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&5
+$as_echo "warning: requested TEA version \"3.9\", have \"${TEA_VERSION}\"" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5
+$as_echo "ok (TEA ${TEA_VERSION})" >&6; }
+ fi
+
+ # If the user did not set CFLAGS, set it now to keep macros
+ # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
+ if test "${CFLAGS+set}" != "set" ; then
+ CFLAGS=""
+ fi
+
+ case "`uname -s`" in
+ *win32*|*WIN32*|*MINGW32_*)
+ # Extract the first word of "cygpath", so it can be a program name with args.
+set dummy cygpath; 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_CYGPATH+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CYGPATH"; then
+ ac_cv_prog_CYGPATH="$CYGPATH" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CYGPATH="cygpath -w"
+ $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_CYGPATH" && ac_cv_prog_CYGPATH="echo"
+fi
+fi
+CYGPATH=$ac_cv_prog_CYGPATH
+if test -n "$CYGPATH"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5
+$as_echo "$CYGPATH" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ EXEEXT=".exe"
+ TEA_PLATFORM="windows"
+ ;;
+ *CYGWIN_*)
+ CYGPATH=echo
+ EXEEXT=".exe"
+ # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
+ ;;
+ *)
+ CYGPATH=echo
+ # Maybe we are cross-compiling....
+ case ${host_alias} in
+ *mingw32*)
+ EXEEXT=".exe"
+ TEA_PLATFORM="windows"
+ ;;
+ *)
+ EXEEXT=""
+ TEA_PLATFORM="unix"
+ ;;
+ esac
+ ;;
+ esac
+
+ # Check if exec_prefix is set. If not use fall back to prefix.
+ # Note when adjusted, so that TEA_PREFIX can correct for this.
+ # This is needed for recursive configures, since autoconf propagates
+ # $prefix, but not $exec_prefix (doh!).
+ if test x$exec_prefix = xNONE ; then
+ exec_prefix_default=yes
+ exec_prefix=$prefix
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5
+$as_echo "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;}
+
+
+
+
+ # This package name must be replaced statically for AC_SUBST to work
+
+ # Substitute STUB_LIB_FILE in case package creates a stub library too.
+
+
+ # We AC_SUBST these here to ensure they are subst'ed,
+ # in case the user doesn't call TEA_ADD_...
+
+
+
+
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in tclconfig "$srcdir"/tclconfig; 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 tclconfig \"$srcdir\"/tclconfig" "$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.
+
+
+
+#--------------------------------------------------------------------
+# Load the tclConfig.sh file
+#--------------------------------------------------------------------
+
+
+
+ #
+ # Ok, lets find the tcl configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tcl
+ #
+
+ if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+
+# Check whether --with-tcl was given.
+if test "${with_tcl+set}" = set; then :
+ withval=$with_tcl; with_tclconfig="${withval}"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5
+$as_echo_n "checking for Tcl configuration... " >&6; }
+ if ${ac_cv_c_tclconfig+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+
+ # First check to see if --with-tcl was specified.
+ if test x"${with_tclconfig}" != x ; then
+ case "${with_tclconfig}" in
+ */tclConfig.sh )
+ if test -f "${with_tclconfig}"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5
+$as_echo "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;}
+ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
+ else
+ as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tcl.framework/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # TEA specific: on Windows, check in common installation locations
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d C:/Tcl/lib 2>/dev/null` \
+ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+fi
+
+
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCL_BIN_DIR="# no Tcl configs found"
+ as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5
+ else
+ no_tcl=
+ TCL_BIN_DIR="${ac_cv_c_tclconfig}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
+ fi
+ 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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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>
+struct stat;
+/* 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
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo_n "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; }
+
+ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
+$as_echo "loading" >&6; }
+ . "${TCL_BIN_DIR}/tclConfig.sh"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5
+$as_echo "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; }
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+
+ # If the TCL_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TCL_LIB_SPEC will be set to the value
+ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+ # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
+ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
+ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tcl.framework installed in an arbitrary location.
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
+ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
+ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
+ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
+ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5
+$as_echo_n "checking platform... " >&6; }
+ hold_cc=$CC; CC="$TCL_CC"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ #ifdef _WIN32
+ #error win32
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ TEA_PLATFORM="unix"
+else
+ TEA_PLATFORM="windows"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CC=$hold_cc
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5
+$as_echo "$TEA_PLATFORM" >&6; }
+
+ # The BUILD_$pkg is to define the correct extern storage class
+ # handling when making this package
+
+cat >>confdefs.h <<_ACEOF
+#define BUILD_${PACKAGE_NAME} /**/
+_ACEOF
+
+ # Do this here as we have fully defined TEA_PLATFORM now
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ EXEEXT=".exe"
+ CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp"
+ fi
+
+ # TEA specific:
+
+
+
+
+
+
+
+
+#--------------------------------------------------------------------
+# Load the tkConfig.sh file if necessary (Tk extension)
+#--------------------------------------------------------------------
+
+
+ #
+ # Ok, lets find the tk configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tk
+ #
+
+ if test x"${no_tk}" = x ; then
+ # we reset no_tk in case something fails here
+ no_tk=true
+
+# Check whether --with-tk was given.
+if test "${with_tk+set}" = set; then :
+ withval=$with_tk; with_tkconfig="${withval}"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk configuration" >&5
+$as_echo_n "checking for Tk configuration... " >&6; }
+ if ${ac_cv_c_tkconfig+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+
+ # First check to see if --with-tkconfig was specified.
+ if test x"${with_tkconfig}" != x ; then
+ case "${with_tkconfig}" in
+ */tkConfig.sh )
+ if test -f "${with_tkconfig}"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&5
+$as_echo "$as_me: WARNING: --with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself" >&2;}
+ with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tkconfig}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
+ else
+ as_fn_error $? "${with_tkconfig} directory doesn't contain tkConfig.sh" "$LINENO" 5
+ fi
+ fi
+
+ # then check for a private Tk library
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../tk[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../tk[8-9].[0-9]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../tk[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../tk[8-9].[0-9]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ../../../tk[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ../../../tk[8-9].[0-9]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tk.framework/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # TEA specific: on Windows, check in common installation locations
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d C:/Tcl/lib 2>/dev/null` \
+ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
+ ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[8-9].[0-9].[0-9]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[8-9].[0-9] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[8-9].[0-9]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+fi
+
+
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ TK_BIN_DIR="# no Tk configs found"
+ as_fn_error $? "Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh" "$LINENO" 5
+ else
+ no_tk=
+ TK_BIN_DIR="${ac_cv_c_tkconfig}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found ${TK_BIN_DIR}/tkConfig.sh" >&5
+$as_echo "found ${TK_BIN_DIR}/tkConfig.sh" >&6; }
+ fi
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of ${TK_BIN_DIR}/tkConfig.sh" >&5
+$as_echo_n "checking for existence of ${TK_BIN_DIR}/tkConfig.sh... " >&6; }
+
+ if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5
+$as_echo "loading" >&6; }
+ . "${TK_BIN_DIR}/tkConfig.sh"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find ${TK_BIN_DIR}/tkConfig.sh" >&5
+$as_echo "could not find ${TK_BIN_DIR}/tkConfig.sh" >&6; }
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
+ eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
+
+ # If the TK_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TK_LIB_SPEC will be set to the value
+ # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
+ # instead of TK_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
+ TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
+ TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tk.framework installed in an arbitrary location.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
+ for i in "`cd "${TK_BIN_DIR}"; pwd`" \
+ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
+ TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
+ TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
+ TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
+ eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
+ eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
+ eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
+
+ # TEA specific: Ensure windowingsystem is defined
+ if test "${TEA_PLATFORM}" = "unix" ; then
+ case ${TK_DEFS} in
+ *MAC_OSX_TK*)
+
+$as_echo "#define MAC_OSX_TK 1" >>confdefs.h
+
+ TEA_WINDOWINGSYSTEM="aqua"
+ ;;
+ *)
+ TEA_WINDOWINGSYSTEM="x11"
+ ;;
+ esac
+ elif test "${TEA_PLATFORM}" = "windows" ; then
+ TEA_WINDOWINGSYSTEM="win32"
+ fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # TEA specific:
+
+
+
+
+#-----------------------------------------------------------------------
+# Handle the --prefix=... option by defaulting to what Tcl gave.
+# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
+#-----------------------------------------------------------------------
+
+
+ if test "${prefix}" = "NONE"; then
+ prefix_default=yes
+ if test x"${TCL_PREFIX}" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5
+$as_echo "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;}
+ prefix=${TCL_PREFIX}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5
+$as_echo "$as_me: --prefix defaulting to /usr/local" >&6;}
+ prefix=/usr/local
+ fi
+ fi
+ if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
+ -o x"${exec_prefix_default}" = x"yes" ; then
+ if test x"${TCL_EXEC_PREFIX}" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5
+$as_echo "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;}
+ exec_prefix=${TCL_EXEC_PREFIX}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5
+$as_echo "$as_me: --exec-prefix defaulting to ${prefix}" >&6;}
+ exec_prefix=$prefix
+ fi
+ fi
+
+
+#-----------------------------------------------------------------------
+# Standard compiler checks.
+# This sets up CC by using the CC env var, or looks for gcc otherwise.
+# This also calls AC_PROG_CC and a few others to create the basic setup
+# necessary to compile executables.
+#-----------------------------------------------------------------------
+
+
+ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
+ # in this macro, they need to go into TEA_SETUP_COMPILER instead.
+
+ 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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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 as_fn_executable_p "$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
+
+{ $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>
+struct stat;
+/* 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
+
+ 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
+
+
+ INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
+
+
+ #--------------------------------------------------------------------
+ # Checks to see if the make program sets the $MAKE variable.
+ #--------------------------------------------------------------------
+
+ { $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
+
+
+ #--------------------------------------------------------------------
+ # Find ranlib
+ #--------------------------------------------------------------------
+
+ 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 as_fn_executable_p "$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 as_fn_executable_p "$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
+
+
+ #--------------------------------------------------------------------
+ # Determines the correct binary file extension (.o, .obj, .exe etc.)
+ #--------------------------------------------------------------------
+
+
+
+
+
+{ $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"
+ as_fn_executable_p "$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"
+ as_fn_executable_p "$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
+
+
+
+ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
+
+
+ #------------------------------------------------------------------------
+ # If we're using GCC, see if the compiler understands -pipe. If so, use it.
+ # It makes compiling go faster. (This is only a performance feature.)
+ #------------------------------------------------------------------------
+
+ if test -z "$no_pipe" -a -n "$GCC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5
+$as_echo_n "checking if the compiler understands -pipe... " >&6; }
+if ${tcl_cv_cc_pipe+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_cc_pipe=yes
+else
+ tcl_cv_cc_pipe=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5
+$as_echo "$tcl_cv_cc_pipe" >&6; }
+ if test $tcl_cv_cc_pipe = yes; then
+ CFLAGS="$CFLAGS -pipe"
+ fi
+ fi
+
+ #--------------------------------------------------------------------
+ # Common compiler flag setup
+ #--------------------------------------------------------------------
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+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
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+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
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+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_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+ if test "${TEA_PLATFORM}" = "unix" ; then
+
+ #--------------------------------------------------------------------
+ # On a few very rare systems, all of the libm.a stuff is
+ # already in libc.a. Set compiler flags accordingly.
+ # Also, Linux requires the "ieee" library for math to work
+ # right (and it must appear before "-lm").
+ #--------------------------------------------------------------------
+
+ ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin"
+if test "x$ac_cv_func_sin" = xyes; then :
+ MATH_LIBS=""
+else
+ MATH_LIBS="-lm"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5
+$as_echo_n "checking for main in -lieee... " >&6; }
+if ${ac_cv_lib_ieee_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lieee $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ieee_main=yes
+else
+ ac_cv_lib_ieee_main=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_ieee_main" >&5
+$as_echo "$ac_cv_lib_ieee_main" >&6; }
+if test "x$ac_cv_lib_ieee_main" = xyes; then :
+ MATH_LIBS="-lieee $MATH_LIBS"
+fi
+
+
+ #--------------------------------------------------------------------
+ # Interactive UNIX requires -linet instead of -lsocket, plus it
+ # needs net/errno.h to define the socket-related error codes.
+ #--------------------------------------------------------------------
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5
+$as_echo_n "checking for main in -linet... " >&6; }
+if ${ac_cv_lib_inet_main+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-linet $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+return main ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_inet_main=yes
+else
+ ac_cv_lib_inet_main=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_inet_main" >&5
+$as_echo "$ac_cv_lib_inet_main" >&6; }
+if test "x$ac_cv_lib_inet_main" = xyes; then :
+ LIBS="$LIBS -linet"
+fi
+
+ ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_errno_h" = xyes; then :
+
+
+$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h
+
+fi
+
+
+
+ #--------------------------------------------------------------------
+ # Check for the existence of the -lsocket and -lnsl libraries.
+ # The order here is important, so that they end up in the right
+ # order in the command line generated by make. Here are some
+ # special considerations:
+ # 1. Use "connect" and "accept" to check for -lsocket, and
+ # "gethostbyname" to check for -lnsl.
+ # 2. Use each function name only once: can't redo a check because
+ # autoconf caches the results of the last check and won't redo it.
+ # 3. Use -lnsl and -lsocket only if they supply procedures that
+ # aren't already present in the normal libraries. This is because
+ # IRIX 5.2 has libraries, but they aren't needed and they're
+ # bogus: they goof up name resolution if used.
+ # 4. On some SVR4 systems, can't use -lsocket without -lnsl too.
+ # To get around this problem, check for both libraries together
+ # if -lsocket doesn't work by itself.
+ #--------------------------------------------------------------------
+
+ tcl_checkBoth=0
+ ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect"
+if test "x$ac_cv_func_connect" = xyes; then :
+ tcl_checkSocket=0
+else
+ tcl_checkSocket=1
+fi
+
+ if test "$tcl_checkSocket" = 1; then
+ ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt"
+if test "x$ac_cv_func_setsockopt" = xyes; then :
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5
+$as_echo_n "checking for setsockopt in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_setsockopt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket $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 setsockopt ();
+int
+main ()
+{
+return setsockopt ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_setsockopt=yes
+else
+ ac_cv_lib_socket_setsockopt=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_setsockopt" >&5
+$as_echo "$ac_cv_lib_socket_setsockopt" >&6; }
+if test "x$ac_cv_lib_socket_setsockopt" = xyes; then :
+ LIBS="$LIBS -lsocket"
+else
+ tcl_checkBoth=1
+fi
+
+fi
+
+ fi
+ if test "$tcl_checkBoth" = 1; then
+ tk_oldLibs=$LIBS
+ LIBS="$LIBS -lsocket -lnsl"
+ ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept"
+if test "x$ac_cv_func_accept" = xyes; then :
+ tcl_checkNsl=0
+else
+ LIBS=$tk_oldLibs
+fi
+
+ fi
+ ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname"
+if test "x$ac_cv_func_gethostbyname" = xyes; then :
+
+else
+ { $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 :
+ LIBS="$LIBS -lnsl"
+fi
+
+fi
+
+
+ # TEA specific: Don't perform the eval of the libraries here because
+ # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS
+
+ TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking dirent.h" >&5
+$as_echo_n "checking dirent.h... " >&6; }
+if ${tcl_cv_dirent_h+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+
+#ifndef _POSIX_SOURCE
+# ifdef __Lynx__
+ /*
+ * Generate compilation error to make the test fail: Lynx headers
+ * are only valid if really in the POSIX environment.
+ */
+
+ missing_procedure();
+# endif
+#endif
+DIR *d;
+struct dirent *entryPtr;
+char *p;
+d = opendir("foobar");
+entryPtr = readdir(d);
+p = entryPtr->d_name;
+closedir(d);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_dirent_h=yes
+else
+ tcl_cv_dirent_h=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: $tcl_cv_dirent_h" >&5
+$as_echo "$tcl_cv_dirent_h" >&6; }
+
+ if test $tcl_cv_dirent_h = no; then
+
+$as_echo "#define NO_DIRENT_H 1" >>confdefs.h
+
+ fi
+
+ # TEA specific:
+ ac_fn_c_check_header_mongrel "$LINENO" "errno.h" "ac_cv_header_errno_h" "$ac_includes_default"
+if test "x$ac_cv_header_errno_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_ERRNO_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "float.h" "ac_cv_header_float_h" "$ac_includes_default"
+if test "x$ac_cv_header_float_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_FLOAT_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "values.h" "ac_cv_header_values_h" "$ac_includes_default"
+if test "x$ac_cv_header_values_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_VALUES_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "limits.h" "ac_cv_header_limits_h" "$ac_includes_default"
+if test "x$ac_cv_header_limits_h" = xyes; then :
+
+$as_echo "#define HAVE_LIMITS_H 1" >>confdefs.h
+
+else
+
+$as_echo "#define NO_LIMITS_H 1" >>confdefs.h
+
+fi
+
+
+ ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtol" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtoul" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strtod" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ if test $tcl_ok = 0; then
+
+$as_echo "#define NO_STDLIB_H 1" >>confdefs.h
+
+ fi
+ ac_fn_c_check_header_mongrel "$LINENO" "string.h" "ac_cv_header_string_h" "$ac_includes_default"
+if test "x$ac_cv_header_string_h" = xyes; then :
+ tcl_ok=1
+else
+ tcl_ok=0
+fi
+
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strstr" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "strerror" >/dev/null 2>&1; then :
+
+else
+ tcl_ok=0
+fi
+rm -f conftest*
+
+
+ # See also memmove check below for a place where NO_STRING_H can be
+ # set and why.
+
+ if test $tcl_ok = 0; then
+
+$as_echo "#define NO_STRING_H 1" >>confdefs.h
+
+ fi
+
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/wait.h" "ac_cv_header_sys_wait_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_wait_h" = xyes; then :
+
+else
+
+$as_echo "#define NO_SYS_WAIT_H 1" >>confdefs.h
+
+fi
+
+
+ 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 :
+
+else
+
+$as_echo "#define NO_DLFCN_H 1" >>confdefs.h
+
+fi
+
+
+
+ # OS/390 lacks sys/param.h (and doesn't need it, by chance).
+ for ac_header in sys/param.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "sys/param.h" "ac_cv_header_sys_param_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_param_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_PARAM_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ # Let the user call this, because if it triggers, they will
+ # need a compat/strtod.c that is correct. Users can also
+ # use Tcl_GetDouble(FromObj) instead.
+ #TEA_BUGGY_STRTOD
+ fi
+
+
+#-----------------------------------------------------------------------
+# __CHANGE__
+# Specify the C source files to compile in TEA_ADD_SOURCES,
+# public headers that need to be installed in TEA_ADD_HEADERS,
+# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
+# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
+# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
+# and PKG_TCL_SOURCES.
+#-----------------------------------------------------------------------
+
+ vars="
+ bltBase64.c
+ bltBgStyle.c
+ bltBind.c
+ bltBitmap.c
+ bltChain.c
+ bltConfig.c
+ bltDBuffer.c
+ bltGrAxis.c
+ bltGrBar.c
+ bltGrElem.c
+ bltGrHairs.c
+ bltGrLegd.c
+ bltGrLine.c
+ bltGrMarker.c
+ bltGrMisc.c
+ bltGrPen.c
+ bltGrPs.c
+ bltGraph.c
+ bltHash.c
+ bltImage.c
+ bltInt.c
+ bltInit.c
+ bltList.c
+ bltNsUtil.c
+ bltParse.c
+ bltPool.c
+ bltPs.c
+ bltPsAfm.c
+ bltSpline.c
+ bltSwitch.c
+ bltText.c
+ bltUnixFont.c
+ bltUnixWindow.c
+ bltUtil.c
+ bltVecCmd.c
+ bltVecMath.c
+ bltVector.c
+ bltWindow.c
+ "
+ for i in $vars; do
+ case $i in
+ \$*)
+ # allow $-var names
+ PKG_SOURCES="$PKG_SOURCES $i"
+ PKG_OBJECTS="$PKG_OBJECTS $i"
+ ;;
+ *)
+ # check for existence - allows for generic/win/unix VPATH
+ # To add more dirs here (like 'src'), you have to update VPATH
+ # in Makefile.in as well
+ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+ -a ! -f "${srcdir}/macosx/$i" \
+ ; then
+ as_fn_error $? "could not find source file '$i'" "$LINENO" 5
+ fi
+ PKG_SOURCES="$PKG_SOURCES $i"
+ # this assumes it is in a VPATH dir
+ i=`basename $i`
+ # handle user calling this before or after TEA_SETUP_COMPILER
+ if test x"${OBJEXT}" != x ; then
+ j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}"
+ else
+ j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}"
+ fi
+ PKG_OBJECTS="$PKG_OBJECTS $j"
+ ;;
+ esac
+ done
+
+
+
+
+ vars="bltVector.h"
+ for i in $vars; do
+ # check for existence, be strict because it is installed
+ if test ! -f "${srcdir}/$i" ; then
+ as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5
+ fi
+ PKG_HEADERS="$PKG_HEADERS $i"
+ done
+
+
+
+ vars="-I. -I\"`${CYGPATH} ${srcdir}`\""
+ for i in $vars; do
+ PKG_INCLUDES="$PKG_INCLUDES $i"
+ done
+
+
+
+ vars=""
+ for i in $vars; do
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
+ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib
+ i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'`
+ fi
+ PKG_LIBS="$PKG_LIBS $i"
+ done
+
+
+
+ PKG_CFLAGS="$PKG_CFLAGS -Wunused"
+
+
+
+ vars=""
+ for i in $vars; do
+ # check for existence - allows for generic/win/unix VPATH
+ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+ -a ! -f "${srcdir}/macosx/$i" \
+ ; then
+ as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5
+ fi
+ PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
+ # this assumes it is in a VPATH dir
+ i=`basename $i`
+ # handle user calling this before or after TEA_SETUP_COMPILER
+ if test x"${OBJEXT}" != x ; then
+ j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}"
+ else
+ j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}"
+ fi
+ PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
+ done
+
+
+
+
+ vars="library/graph.tcl library/bltGraph.pro"
+ for i in $vars; do
+ # check for existence, be strict because it is installed
+ if test ! -f "${srcdir}/$i" ; then
+ as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5
+ fi
+ PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
+ done
+
+
+
+#--------------------------------------------------------------------
+# __CHANGE__
+#
+# You can add more files to clean if your extension creates any extra
+# files by extending CLEANFILES.
+# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
+# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
+#
+# A few miscellaneous platform-specific items:
+# TEA_ADD_* any platform specific compiler/build info here.
+#--------------------------------------------------------------------
+
+CLEANFILES="$CLEANFILES config.status config.log Makefile"
+if test "${TEA_PLATFORM}" = "windows" ; then
+ # Ensure no empty if clauses
+ :
+ #TEA_ADD_SOURCES([win/winFile.c])
+ #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
+else
+ # Ensure no empty else clauses
+ :
+ #TEA_ADD_SOURCES([unix/unixFile.c])
+ #TEA_ADD_LIBS([-lsuperfly])
+fi
+
+#--------------------------------------------------------------------
+# __CHANGE__
+# Choose which headers you need. Extension authors should try very
+# hard to only rely on the Tcl public header files. Internal headers
+# contain private data structures and are subject to change without
+# notice.
+# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
+#--------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5
+$as_echo_n "checking for Tcl public headers... " >&6; }
+
+
+# Check whether --with-tclinclude was given.
+if test "${with_tclinclude+set}" = set; then :
+ withval=$with_tclinclude; with_tclinclude=${withval}
+fi
+
+
+ if ${ac_cv_c_tclh+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # Use the value from --with-tclinclude, if it was given
+
+ if test x"${with_tclinclude}" != x ; then
+ if test -f "${with_tclinclude}/tcl.h" ; then
+ ac_cv_c_tclh=${with_tclinclude}
+ else
+ as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5
+ fi
+ else
+ list=""
+ if test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use
+ # the framework's Headers directory
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`"
+ ;;
+ esac
+ fi
+
+ # Look in the source dir only if Tcl is not installed,
+ # and in that situation, look there before installed locations.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`"
+ fi
+
+ # Check order: pkg --prefix location, Tcl's --prefix location,
+ # relative to directory of tclConfig.sh.
+
+ eval "temp_includedir=${includedir}"
+ list="$list \
+ `ls -d ${temp_includedir} 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
+ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+ list="$list /usr/local/include /usr/include"
+ if test x"${TCL_INCLUDE_SPEC}" != x ; then
+ d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'`
+ list="$list `ls -d ${d} 2>/dev/null`"
+ fi
+ fi
+ for i in $list ; do
+ if test -f "$i/tcl.h" ; then
+ ac_cv_c_tclh=$i
+ break
+ fi
+ done
+ fi
+
+fi
+
+
+ # Print a message based on how we determined the include path
+
+ if test x"${ac_cv_c_tclh}" = x ; then
+ as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5
+$as_echo "${ac_cv_c_tclh}" >&6; }
+ fi
+
+ # Convert to a native path and substitute into the output files.
+
+ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`
+
+ TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+
+
+
+ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tcl private include files" >&5
+$as_echo_n "checking for Tcl private include files... " >&6; }
+
+ TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`
+ TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\"
+
+ # Check to see if tcl<Plat>Port.h isn't already with the public headers
+ # Don't look for tclInt.h because that resides with tcl.h in the core
+ # sources, but the <plat>Port headers are in a different directory
+ if test "${TEA_PLATFORM}" = "windows" -a \
+ -f "${ac_cv_c_tclh}/tclWinPort.h"; then
+ result="private headers found with public headers"
+ elif test "${TEA_PLATFORM}" = "unix" -a \
+ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then
+ result="private headers found with public headers"
+ else
+ TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\"
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\"
+ else
+ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\"
+ fi
+ # Overwrite the previous TCL_INCLUDES as this should capture both
+ # public and private headers in the same set.
+ # We want to ensure these are substituted so as not to require
+ # any *_NATIVE vars be defined in the Makefile
+ TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
+ if test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use
+ # the framework's Headers and PrivateHeaders directories
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -d "${TCL_BIN_DIR}/Headers" -a \
+ -d "${TCL_BIN_DIR}/PrivateHeaders"; then
+ TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}"
+ else
+ TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
+ fi
+ ;;
+ esac
+ result="Using ${TCL_INCLUDES}"
+ else
+ if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then
+ as_fn_error $? "Cannot find private header tclInt.h in ${TCL_SRC_DIR}" "$LINENO" 5
+ fi
+ result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}"
+ fi
+ fi
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${result}" >&5
+$as_echo "${result}" >&6; }
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk public headers" >&5
+$as_echo_n "checking for Tk public headers... " >&6; }
+
+
+# Check whether --with-tkinclude was given.
+if test "${with_tkinclude+set}" = set; then :
+ withval=$with_tkinclude; with_tkinclude=${withval}
+fi
+
+
+ if ${ac_cv_c_tkh+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # Use the value from --with-tkinclude, if it was given
+
+ if test x"${with_tkinclude}" != x ; then
+ if test -f "${with_tkinclude}/tk.h" ; then
+ ac_cv_c_tkh=${with_tkinclude}
+ else
+ as_fn_error $? "${with_tkinclude} directory does not contain tk.h" "$LINENO" 5
+ fi
+ else
+ list=""
+ if test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use
+ # the framework's Headers directory.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`"
+ ;;
+ esac
+ fi
+
+ # Look in the source dir only if Tk is not installed,
+ # and in that situation, look there before installed locations.
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`"
+ fi
+
+ # Check order: pkg --prefix location, Tk's --prefix location,
+ # relative to directory of tkConfig.sh, Tcl's --prefix location,
+ # relative to directory of tclConfig.sh.
+
+ eval "temp_includedir=${includedir}"
+ list="$list \
+ `ls -d ${temp_includedir} 2>/dev/null` \
+ `ls -d ${TK_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
+ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+ list="$list /usr/local/include /usr/include"
+ if test x"${TK_INCLUDE_SPEC}" != x ; then
+ d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'`
+ list="$list `ls -d ${d} 2>/dev/null`"
+ fi
+ fi
+ for i in $list ; do
+ if test -f "$i/tk.h" ; then
+ ac_cv_c_tkh=$i
+ break
+ fi
+ done
+ fi
+
+fi
+
+
+ # Print a message based on how we determined the include path
+
+ if test x"${ac_cv_c_tkh}" = x ; then
+ as_fn_error $? "tk.h not found. Please specify its location with --with-tkinclude" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tkh}" >&5
+$as_echo "${ac_cv_c_tkh}" >&6; }
+ fi
+
+ # Convert to a native path and substitute into the output files.
+
+ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`
+
+ TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+
+
+ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ # On Windows and Aqua, we need the X compat headers
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5
+$as_echo_n "checking for X11 header files... " >&6; }
+ if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
+ INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
+ TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${INCLUDE_DIR_NATIVE}" >&5
+$as_echo "${INCLUDE_DIR_NATIVE}" >&6; }
+ fi
+
+
+ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Tk private include files" >&5
+$as_echo_n "checking for Tk private include files... " >&6; }
+
+ TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`
+ TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\"
+
+ # Check to see if tk<Plat>Port.h isn't already with the public headers
+ # Don't look for tkInt.h because that resides with tk.h in the core
+ # sources, but the <plat>Port headers are in a different directory
+ if test "${TEA_PLATFORM}" = "windows" -a \
+ -f "${ac_cv_c_tkh}/tkWinPort.h"; then
+ result="private headers found with public headers"
+ elif test "${TEA_PLATFORM}" = "unix" -a \
+ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then
+ result="private headers found with public headers"
+ else
+ TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\"
+ TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\"
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\"
+ else
+ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\"
+ fi
+ # Overwrite the previous TK_INCLUDES as this should capture both
+ # public and private headers in the same set.
+ # We want to ensure these are substituted so as not to require
+ # any *_NATIVE vars be defined in the Makefile
+ TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}"
+ # Detect and add ttk subdir
+ if test -d "${TK_SRC_DIR}/generic/ttk"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
+ fi
+ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
+ fi
+ if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
+ fi
+ if test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use
+ # the framework's Headers and PrivateHeaders directories
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -d "${TK_BIN_DIR}/Headers" -a \
+ -d "${TK_BIN_DIR}/PrivateHeaders"; then
+ TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}"
+ else
+ TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
+ fi
+ ;;
+ esac
+ result="Using ${TK_INCLUDES}"
+ else
+ if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then
+ as_fn_error $? "Cannot find private header tkInt.h in ${TK_SRC_DIR}" "$LINENO" 5
+ fi
+ result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}"
+ fi
+ fi
+
+
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${result}" >&5
+$as_echo "${result}" >&6; }
+
+#TEA_PATH_X
+
+#--------------------------------------------------------------------
+# Check whether --enable-threads or --disable-threads was given.
+# This auto-enables if Tcl was compiled threaded.
+#--------------------------------------------------------------------
+
+
+ # Check whether --enable-threads was given.
+if test "${enable_threads+set}" = set; then :
+ enableval=$enable_threads; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+
+ if test "${enable_threads+set}" = set; then
+ enableval="$enable_threads"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+ TCL_THREADS=1
+
+ if test "${TEA_PLATFORM}" != "windows" ; then
+ # We are always OK on Windows, so check what this platform wants:
+
+ # USE_THREAD_ALLOC tells us to try the special thread-based
+ # allocator that significantly reduces lock contention
+
+$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+ if test "`uname -s`" = "SunOS" ; then
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+ fi
+
+$as_echo "#define _THREAD_SAFE 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5
+$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $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 pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_mutex_init=yes
+else
+ ac_cv_lib_pthread_pthread_mutex_init=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_pthread_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "no"; then
+ # Check a little harder for __pthread_mutex_init in the same
+ # library, as some systems hide it there until pthread.h is
+ # defined. We could alternatively do an AC_TRY_COMPILE with
+ # pthread.h, but that will work with libpthread really doesn't
+ # exist, like AIX 4.2. [Bug: 4359]
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5
+$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $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 __pthread_mutex_init ();
+int
+main ()
+{
+return __pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread___pthread_mutex_init=yes
+else
+ ac_cv_lib_pthread___pthread_mutex_init=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_pthread___pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthread"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5
+$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; }
+if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreads $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 pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthreads_pthread_mutex_init=yes
+else
+ ac_cv_lib_pthreads_pthread_mutex_init=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_pthreads_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthreads"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5
+$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; }
+if ${ac_cv_lib_c_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc $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 pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_c_pthread_mutex_init=yes
+else
+ ac_cv_lib_c_pthread_mutex_init=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_c_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5
+$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; }
+if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lc_r $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 pthread_mutex_init ();
+int
+main ()
+{
+return pthread_mutex_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_c_r_pthread_mutex_init=yes
+else
+ ac_cv_lib_c_r_pthread_mutex_init=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_c_r_pthread_mutex_init" >&5
+$as_echo "$ac_cv_lib_c_r_pthread_mutex_init" >&6; }
+if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes; then :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -pthread"
+ else
+ TCL_THREADS=0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5
+$as_echo "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;}
+ fi
+ fi
+ fi
+ fi
+ fi
+ else
+ TCL_THREADS=0
+ fi
+ # Do checking message here to not mess up interleaved configure output
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5
+$as_echo_n "checking for building with threads... " >&6; }
+ if test "${TCL_THREADS}" = 1; then
+
+$as_echo "#define TCL_THREADS 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5
+$as_echo "yes (default)" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+ # TCL_THREADS sanity checking. See if our request for building with
+ # threads is the same as the way Tcl was built. If not, warn the user.
+ case ${TCL_DEFS} in
+ *THREADS=1*)
+ if test "${TCL_THREADS}" = "0"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
+ that IS thread-enabled. It is recommended to use --enable-threads." >&5
+$as_echo "$as_me: WARNING:
+ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
+ that IS thread-enabled. It is recommended to use --enable-threads." >&2;}
+ fi
+ ;;
+ *)
+ if test "${TCL_THREADS}" = "1"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ --enable-threads requested, but building against a Tcl that is NOT
+ thread-enabled. This is an OK configuration that will also run in
+ a thread-enabled core." >&5
+$as_echo "$as_me: WARNING:
+ --enable-threads requested, but building against a Tcl that is NOT
+ thread-enabled. This is an OK configuration that will also run in
+ a thread-enabled core." >&2;}
+ fi
+ ;;
+ esac
+
+
+
+#--------------------------------------------------------------------
+# The statement below defines a collection of symbols related to
+# building as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5
+$as_echo_n "checking how to build libraries... " >&6; }
+ # Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared; tcl_ok=$enableval
+else
+ tcl_ok=yes
+fi
+
+
+ if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5
+$as_echo "shared" >&6; }
+ SHARED_BUILD=1
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
+$as_echo "static" >&6; }
+ SHARED_BUILD=0
+
+$as_echo "#define STATIC_BUILD 1" >>confdefs.h
+
+ fi
+
+
+
+#--------------------------------------------------------------------
+# This macro figures out what flags to use with the compiler/linker
+# when building shared/static debug/optimized objects. This information
+# can be taken from the tclConfig.sh file, but this figures it all out.
+#--------------------------------------------------------------------
+
+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 as_fn_executable_p "$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 as_fn_executable_p "$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
+
+
+
+
+ # Step 0.a: Enable 64 bit support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5
+$as_echo_n "checking if 64bit support is requested... " >&6; }
+ # Check whether --enable-64bit was given.
+if test "${enable_64bit+set}" = set; then :
+ enableval=$enable_64bit; do64bit=$enableval
+else
+ do64bit=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5
+$as_echo "$do64bit" >&6; }
+
+ # Step 0.b: Enable Solaris 64 bit VIS support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5
+$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; }
+ # Check whether --enable-64bit-vis was given.
+if test "${enable_64bit_vis+set}" = set; then :
+ enableval=$enable_64bit_vis; do64bitVIS=$enableval
+else
+ do64bitVIS=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5
+$as_echo "$do64bitVIS" >&6; }
+ # Force 64bit on with VIS
+ if test "$do64bitVIS" = "yes"; then :
+ do64bit=yes
+fi
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5
+$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; }
+if ${tcl_cv_cc_visibility_hidden+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}
+int
+main ()
+{
+f();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_visibility_hidden=yes
+else
+ tcl_cv_cc_visibility_hidden=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5
+$as_echo "$tcl_cv_cc_visibility_hidden" >&6; }
+ if test $tcl_cv_cc_visibility_hidden = yes; then :
+
+
+$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h
+
+
+$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h
+
+
+fi
+
+ # Step 0.d: Disable -rpath support?
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5
+$as_echo_n "checking if rpath support is requested... " >&6; }
+ # Check whether --enable-rpath was given.
+if test "${enable_rpath+set}" = set; then :
+ enableval=$enable_rpath; doRpath=$enableval
+else
+ doRpath=yes
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5
+$as_echo "$doRpath" >&6; }
+
+ # TEA specific: Cross-compiling options for Windows/CE builds?
+
+ if test "${TEA_PLATFORM}" = windows; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested" >&5
+$as_echo_n "checking if Windows/CE build is requested... " >&6; }
+ # Check whether --enable-wince was given.
+if test "${enable_wince+set}" = set; then :
+ enableval=$enable_wince; doWince=$enableval
+else
+ doWince=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doWince" >&5
+$as_echo "$doWince" >&6; }
+
+fi
+
+ # Set the variable "system" to hold the name and version number
+ # for the system.
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5
+$as_echo_n "checking system version... " >&6; }
+if ${tcl_cv_sys_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # TEA specific:
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ tcl_cv_sys_version=windows
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5
+$as_echo "$as_me: WARNING: can't find uname command" >&2;}
+ tcl_cv_sys_version=unknown
+ else
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ fi
+ fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5
+$as_echo "$tcl_cv_sys_version" >&6; }
+ system=$tcl_cv_sys_version
+
+
+ # Require ranlib early so we can override it in special cases below.
+
+
+
+ # Set configuration options based on system name and version.
+ # This is similar to Tcl's unix/tcl.m4 except that we've added a
+ # "windows" case and removed some core-only vars.
+
+ do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
+ UNSHARED_LIB_SUFFIX=""
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
+ ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
+ TCL_LIB_VERSIONS_OK=ok
+ CFLAGS_DEBUG=-g
+ if test "$GCC" = yes; then :
+
+ CFLAGS_OPTIMIZE=-O2
+ CFLAGS_WARNING="-Wall"
+
+else
+
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING=""
+
+fi
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; 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_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $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
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; 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_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $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_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ 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
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+ STLIB_LD='${AR} cr'
+ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+ if test "x$SHLIB_VERSION" = x; then :
+ SHLIB_VERSION="1.0"
+fi
+ case $system in
+ # TEA specific:
+ windows)
+ # This is a 2-stage check to make sure we have the 64-bit SDK
+ # We have to know where the SDK is installed.
+ # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
+ # MACHINE is IX86 for LINK, but this is used by the manifest,
+ # which requires x86|amd64|ia64.
+ MACHINE="X86"
+ if test "$do64bit" != "no" ; then
+ if test "x${MSSDK}x" = "xx" ; then
+ MSSDK="C:/Progra~1/Microsoft Platform SDK"
+ fi
+ MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
+ PATH64=""
+ case "$do64bit" in
+ amd64|x64|yes)
+ MACHINE="AMD64" ; # default to AMD64 64-bit build
+ PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
+ ;;
+ ia64)
+ MACHINE="IA64"
+ PATH64="${MSSDK}/Bin/Win64"
+ ;;
+ esac
+ if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5
+$as_echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed" >&5
+$as_echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;}
+ do64bit="no"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5
+$as_echo " Using 64-bit $MACHINE mode" >&6; }
+ do64bit_ok="yes"
+ fi
+ fi
+
+ if test "$doWince" != "no" ; then
+ if test "$do64bit" != "no" ; then
+ as_fn_error $? "Windows/CE and 64-bit builds incompatible" "$LINENO" 5
+ fi
+ if test "$GCC" = "yes" ; then
+ as_fn_error $? "Windows/CE and GCC builds incompatible" "$LINENO" 5
+ fi
+
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-celib
+
+ if test x"${no_celib}" = x ; then
+ # we reset no_celib in case something fails here
+ no_celib=true
+
+# Check whether --with-celib was given.
+if test "${with_celib+set}" = set; then :
+ withval=$with_celib; with_celibconfig=${withval}
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory" >&5
+$as_echo_n "checking for Windows/CE celib directory... " >&6; }
+ if ${ac_cv_c_celibconfig+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ # First check to see if --with-celibconfig was specified.
+ if test x"${with_celibconfig}" != x ; then
+ if test -d "${with_celibconfig}/inc" ; then
+ ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
+ else
+ as_fn_error $? "${with_celibconfig} directory doesn't contain inc directory" "$LINENO" 5
+ fi
+ fi
+
+ # then check for a celib library
+ if test x"${ac_cv_c_celibconfig}" = x ; then
+ for i in \
+ ../celib-palm-3.0 \
+ ../celib \
+ ../../celib-palm-3.0 \
+ ../../celib \
+ `ls -dr ../celib-*3.[0-9]* 2>/dev/null` \
+ ${srcdir}/../celib-palm-3.0 \
+ ${srcdir}/../celib \
+ `ls -dr ${srcdir}/../celib-*3.[0-9]* 2>/dev/null` \
+ ; do
+ if test -d "$i/inc" ; then
+ ac_cv_c_celibconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+
+fi
+
+ if test x"${ac_cv_c_celibconfig}" = x ; then
+ as_fn_error $? "Cannot find celib support library directory" "$LINENO" 5
+ else
+ no_celib=
+ CELIB_DIR=${ac_cv_c_celibconfig}
+ CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found $CELIB_DIR" >&5
+$as_echo "found $CELIB_DIR" >&6; }
+ fi
+ fi
+
+ # Set defaults for common evc4/PPC2003 setup
+ # Currently Tcl requires 300+, possibly 420+ for sockets
+ CEVERSION=420; # could be 211 300 301 400 420 ...
+ TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ...
+ ARCH=ARM; # could be ARM MIPS X86EM ...
+ PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
+ if test "$doWince" != "yes"; then
+ # If !yes then the user specified something
+ # Reset ARCH to allow user to skip specifying it
+ ARCH=
+ eval `echo $doWince | awk -F, '{ \
+ if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \
+ if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
+ if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \
+ if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \
+ if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \
+ }'`
+ if test "x${ARCH}" = "x" ; then
+ ARCH=$TARGETCPU;
+ fi
+ fi
+ OSVERSION=WCE$CEVERSION;
+ if test "x${WCEROOT}" = "x" ; then
+ WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
+ if test ! -d "${WCEROOT}" ; then
+ WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
+ fi
+ fi
+ if test "x${SDKROOT}" = "x" ; then
+ SDKROOT="C:/Program Files/Windows CE Tools"
+ if test ! -d "${SDKROOT}" ; then
+ SDKROOT="C:/Windows CE Tools"
+ fi
+ fi
+ WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
+ SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
+ if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
+ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
+ as_fn_error $? "could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" "$LINENO" 5
+ doWince="no"
+ else
+ # We could PATH_NOSPACE these, but that's not important,
+ # as long as we quote them when used.
+ CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
+ if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
+ CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
+ fi
+ CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
+ fi
+ fi
+
+ if test "$GCC" != "yes" ; then
+ if test "${SHARED_BUILD}" = "0" ; then
+ runtime=-MT
+ else
+ runtime=-MD
+ fi
+
+ if test "$do64bit" != "no" ; then
+ # All this magic is necessary for the Win64 SDK RC1 - hobbs
+ CC="\"${PATH64}/cl.exe\""
+ CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
+ RC="\"${MSSDK}/bin/rc.exe\""
+ lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
+ LINKBIN="\"${PATH64}/link.exe\""
+ CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
+ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+ # Avoid 'unresolved external symbol __security_cookie'
+ # errors, c.f. http://support.microsoft.com/?id=894573
+
+ vars="bufferoverflowU.lib"
+ for i in $vars; do
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
+ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib
+ i=`echo "$i" | sed -e 's/^\([^-].*\)\.lib$/-l\1/i'`
+ fi
+ PKG_LIBS="$PKG_LIBS $i"
+ done
+
+
+ elif test "$doWince" != "no" ; then
+ CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
+ if test "${TARGETCPU}" = "X86"; then
+ CC="\"${CEBINROOT}/cl.exe\""
+ else
+ CC="\"${CEBINROOT}/cl${ARCH}.exe\""
+ fi
+ CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
+ RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
+ arch=`echo ${ARCH} | awk '{print tolower($0)}'`
+ defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
+ if test "${SHARED_BUILD}" = "1" ; then
+ # Static CE builds require static celib as well
+ defs="${defs} _DLL"
+ fi
+ for i in $defs ; do
+
+cat >>confdefs.h <<_ACEOF
+#define $i 1
+_ACEOF
+
+ done
+
+cat >>confdefs.h <<_ACEOF
+#define _WIN32_WCE $CEVERSION
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define UNDER_CE $CEVERSION
+_ACEOF
+
+ CFLAGS_DEBUG="-nologo -Zi -Od"
+ CFLAGS_OPTIMIZE="-nologo -Ox"
+ lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
+ lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
+ LINKBIN="\"${CEBINROOT}/link.exe\""
+
+ else
+ RC="rc"
+ lflags="-nologo"
+ LINKBIN="link"
+ CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
+ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+ fi
+ fi
+
+ if test "$GCC" = "yes"; then
+ # mingw gcc mode
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args.
+set dummy ${ac_tool_prefix}windres; 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_RC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RC"; then
+ ac_cv_prog_RC="$RC" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RC="${ac_tool_prefix}windres"
+ $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
+RC=$ac_cv_prog_RC
+if test -n "$RC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RC" >&5
+$as_echo "$RC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RC"; then
+ ac_ct_RC=$RC
+ # Extract the first word of "windres", so it can be a program name with args.
+set dummy windres; 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_RC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RC"; then
+ ac_cv_prog_ac_ct_RC="$ac_ct_RC" # 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 as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RC="windres"
+ $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_RC=$ac_cv_prog_ac_ct_RC
+if test -n "$ac_ct_RC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5
+$as_echo "$ac_ct_RC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RC" = x; then
+ RC=""
+ 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
+ RC=$ac_ct_RC
+ fi
+else
+ RC="$ac_cv_prog_RC"
+fi
+
+ CFLAGS_DEBUG="-g"
+ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+ SHLIB_LD='${CC} -shared'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
+ LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5
+$as_echo_n "checking for cross-compile version of gcc... " >&6; }
+if ${ac_cv_cross+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #ifdef __WIN32__
+ #error cross-compiler
+ #endif
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_cross=yes
+else
+ ac_cv_cross=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5
+$as_echo "$ac_cv_cross" >&6; }
+ if test "$ac_cv_cross" = "yes"; then
+ case "$do64bit" in
+ amd64|x64|yes)
+ CC="x86_64-w64-mingw32-gcc"
+ LD="x86_64-w64-mingw32-ld"
+ AR="x86_64-w64-mingw32-ar"
+ RANLIB="x86_64-w64-mingw32-ranlib"
+ RC="x86_64-w64-mingw32-windres"
+ ;;
+ *)
+ CC="i686-w64-mingw32-gcc"
+ LD="i686-w64-mingw32-ld"
+ AR="i686-w64-mingw32-ar"
+ RANLIB="i686-w64-mingw32-ranlib"
+ RC="i686-w64-mingw32-windres"
+ ;;
+ esac
+ fi
+
+ else
+ SHLIB_LD="${LINKBIN} -dll ${lflags}"
+ # link -lib only works when -lib is the first arg
+ STLIB_LD="${LINKBIN} -lib ${lflags}"
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
+ PATHTYPE=-w
+ # For information on what debugtype is most useful, see:
+ # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+ # and also
+ # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
+ # This essentially turns it all on.
+ LDFLAGS_DEBUG="-debug -debugtype:cv"
+ LDFLAGS_OPTIMIZE="-release"
+ if test "$doWince" != "no" ; then
+ LDFLAGS_CONSOLE="-link ${lflags}"
+ LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
+ else
+ LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
+ LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
+ fi
+ fi
+
+ SHLIB_SUFFIX=".dll"
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'
+
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ AIX-*)
+ if test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"; then :
+
+ # AIX requires the _r compiler when gcc isn't being used
+ case "${CC}" in
+ *_r|*_r\ *)
+ # ok ...
+ ;;
+ *)
+ # Make sure only first arg gets _r
+ CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'`
+ ;;
+ esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5
+$as_echo "Using $CC for compiling with threads" >&6; }
+
+fi
+ LIBS="$LIBS -lc"
+ SHLIB_CFLAGS=""
+ SHLIB_SUFFIX=".so"
+
+ LD_LIBRARY_PATH_VAR="LIBPATH"
+
+ # Check to enable 64-bit flags for compiler/linker
+ if test "$do64bit" = yes; then :
+
+ if test "$GCC" = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
+
+else
+
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
+ RANLIB="${RANLIB} -X64"
+ AR="${AR} -X64"
+ SHLIB_LD_FLAGS="-b64"
+
+fi
+
+fi
+
+ if test "`uname -m`" = ia64; then :
+
+ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ if test "$GCC" = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+
+else
+
+ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+
+fi
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+
+else
+
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+
+else
+
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+
+fi
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+fi
+ ;;
+ BeOS*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -nostart'
+ SHLIB_SUFFIX=".so"
+
+ #-----------------------------------------------------------
+ # Check for inet_ntoa in -lbind, for BeOS (which also needs
+ # -lsocket, even if the network functions are in -lnet which
+ # is always linked to, for compatibility.
+ #-----------------------------------------------------------
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5
+$as_echo_n "checking for inet_ntoa in -lbind... " >&6; }
+if ${ac_cv_lib_bind_inet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lbind $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 inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_bind_inet_ntoa=yes
+else
+ ac_cv_lib_bind_inet_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_bind_inet_ntoa" >&5
+$as_echo "$ac_cv_lib_bind_inet_ntoa" >&6; }
+if test "x$ac_cv_lib_bind_inet_ntoa" = xyes; then :
+ LIBS="$LIBS -lbind -lsocket"
+fi
+
+ ;;
+ BSD/OS-4.*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".so"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ CYGWIN_*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".dll"
+ EXEEXT=".exe"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5
+$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; }
+if ${ac_cv_lib_network_inet_ntoa+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnetwork $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 inet_ntoa ();
+int
+main ()
+{
+return inet_ntoa ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_network_inet_ntoa=yes
+else
+ ac_cv_lib_network_inet_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_network_inet_ntoa" >&5
+$as_echo "$ac_cv_lib_network_inet_ntoa" >&6; }
+if test "x$ac_cv_lib_network_inet_ntoa" = xyes; then :
+ LIBS="$LIBS -lnetwork"
+fi
+
+ ;;
+ HP-UX-*.11.*)
+ # Use updated header definitions where possible
+
+$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h
+
+ # TEA specific: Needed by Tcl, but not most extensions
+ #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
+ #LIBS="$LIBS -lxnet" # Use the XOPEN network library
+
+ if test "`uname -m`" = ia64; then :
+
+ SHLIB_SUFFIX=".so"
+ # Use newer C++ library for C++ extensions
+ #if test "$GCC" != "yes" ; then
+ # CPPFLAGS="-AA"
+ #fi
+
+else
+
+ SHLIB_SUFFIX=".sl"
+
+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 :
+ tcl_ok=yes
+else
+ tcl_ok=no
+fi
+
+ if test "$tcl_ok" = yes; then :
+
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+
+fi
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+else
+
+ CFLAGS="$CFLAGS -z"
+ # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
+ #CFLAGS="$CFLAGS +DAportable"
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+
+fi
+
+ # Check to enable 64-bit flags for compiler/linker
+ if test "$do64bit" = "yes"; then :
+
+ if test "$GCC" = yes; then :
+
+ case `${CC} -dumpmachine` in
+ hppa64*)
+ # 64-bit gcc in use. Fix flags for GNU ld.
+ do64bit_ok=yes
+ SHLIB_LD='${CC} -shared'
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;}
+ ;;
+ esac
+
+else
+
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS +DD64"
+ LDFLAGS_ARCH="+DD64"
+
+fi
+
+fi ;;
+ IRIX-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+ if test "$GCC" = yes; then :
+
+ CFLAGS="$CFLAGS -mabi=n32"
+ LDFLAGS="$LDFLAGS -mabi=n32"
+
+else
+
+ case $system in
+ IRIX-6.3)
+ # Use to build 6.2 compatible binaries on 6.3.
+ CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
+ ;;
+ *)
+ CFLAGS="$CFLAGS -n32"
+ ;;
+ esac
+ LDFLAGS="$LDFLAGS -n32"
+
+fi
+ ;;
+ IRIX64-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+
+ # Check to enable 64-bit flags for compiler/linker
+
+ if test "$do64bit" = yes; then :
+
+ if test "$GCC" = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;}
+
+else
+
+ do64bit_ok=yes
+ SHLIB_LD="ld -64 -shared -rdata_shared"
+ CFLAGS="$CFLAGS -64"
+ LDFLAGS_ARCH="-64"
+
+fi
+
+fi
+ ;;
+ Linux*|GNU*|NetBSD-Debian)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+
+ # TEA specific:
+ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "`uname -m`" = "alpha"; then :
+ CFLAGS="$CFLAGS -mieee"
+fi
+ if test $do64bit = yes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5
+$as_echo_n "checking if compiler accepts -m64 flag... " >&6; }
+if ${tcl_cv_cc_m64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -m64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_m64=yes
+else
+ tcl_cv_cc_m64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5
+$as_echo "$tcl_cv_cc_m64" >&6; }
+ if test $tcl_cv_cc_m64 = yes; then :
+
+ CFLAGS="$CFLAGS -m64"
+ do64bit_ok=yes
+
+fi
+
+fi
+
+ # The combo of gcc + glibc has a bug related to inlining of
+ # functions like strtod(). The -fno-builtin flag should address
+ # this problem but it does not work. The -fno-inline flag is kind
+ # of overkill but it works. Disable inlining only when one of the
+ # files in compat/*.c is being linked in.
+
+ if test x"${USE_COMPAT}" != x; then :
+ CFLAGS="$CFLAGS -fno-inline"
+fi
+ ;;
+ Lynx*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ CFLAGS_OPTIMIZE=-02
+ SHLIB_LD='${CC} -shared'
+ LD_FLAGS="-Wl,--export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ ;;
+ OpenBSD-*)
+ arch=`arch -s`
+ case "$arch" in
+ vax)
+ SHLIB_SUFFIX=""
+ SHARED_LIB_SUFFIX=""
+ LDFLAGS=""
+ ;;
+ *)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ LDFLAGS="-Wl,-export-dynamic"
+ ;;
+ esac
+ case "$arch" in
+ vax)
+ CFLAGS_OPTIMIZE="-O1"
+ ;;
+ *)
+ CFLAGS_OPTIMIZE="-O2"
+ ;;
+ esac
+ if test "${TCL_THREADS}" = "1"; then :
+
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+
+fi
+ # OpenBSD doesn't do version numbers with dots.
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ NetBSD-*)
+ # NetBSD has ELF and can use 'cc -shared' to build shared libs
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "${TCL_THREADS}" = "1"; then :
+
+ # The -pthread needs to go in the CFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+
+fi
+ ;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$@"
+ SHLIB_SUFFIX=".so"
+ LDFLAGS=""
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+fi
+ if test "${TCL_THREADS}" = "1"; then :
+
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"
+fi
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ Darwin-*)
+ CFLAGS_OPTIMIZE="-Os"
+ SHLIB_CFLAGS="-fno-common"
+ # To avoid discrepancies between what headers configure sees during
+ # preprocessing tests and compiling tests, move any -isysroot and
+ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
+ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`"
+ CFLAGS="`echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`"
+ if test $do64bit = yes; then :
+
+ case `arch` in
+ ppc)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5
+$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; }
+if ${tcl_cv_cc_arch_ppc64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_arch_ppc64=yes
+else
+ tcl_cv_cc_arch_ppc64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5
+$as_echo "$tcl_cv_cc_arch_ppc64" >&6; }
+ if test $tcl_cv_cc_arch_ppc64 = yes; then :
+
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ do64bit_ok=yes
+
+fi;;
+ i386)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5
+$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; }
+if ${tcl_cv_cc_arch_x86_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch x86_64"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_cc_arch_x86_64=yes
+else
+ tcl_cv_cc_arch_x86_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS=$hold_cflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5
+$as_echo "$tcl_cv_cc_arch_x86_64" >&6; }
+ if test $tcl_cv_cc_arch_x86_64 = yes; then :
+
+ CFLAGS="$CFLAGS -arch x86_64"
+ do64bit_ok=yes
+
+fi;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5
+$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};;
+ esac
+
+else
+
+ # Check for combined 32-bit and 64-bit fat build
+ if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '; then :
+
+ fat_32_64=yes
+fi
+
+fi
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5
+$as_echo_n "checking if ld accepts -single_module flag... " >&6; }
+if ${tcl_cv_ld_single_module+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_single_module=yes
+else
+ tcl_cv_ld_single_module=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5
+$as_echo "$tcl_cv_ld_single_module" >&6; }
+ if test $tcl_cv_ld_single_module = yes; then :
+
+ SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+
+fi
+ # TEA specific: link shlib with current and compatibility version flags
+ vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
+ SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
+ SHLIB_SUFFIX=".dylib"
+ # Don't use -prebind when building for Mac OS X 10.4 or later only:
+ if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then :
+
+ LDFLAGS="$LDFLAGS -prebind"
+fi
+ LDFLAGS="$LDFLAGS -headerpad_max_install_names"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5
+$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; }
+if ${tcl_cv_ld_search_paths_first+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_search_paths_first=yes
+else
+ tcl_cv_ld_search_paths_first=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5
+$as_echo "$tcl_cv_ld_search_paths_first" >&6; }
+ if test $tcl_cv_ld_search_paths_first = yes; then :
+
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+
+fi
+ if test "$tcl_cv_cc_visibility_hidden" != yes; then :
+
+
+$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h
+
+ tcl_cv_cc_visibility_hidden=yes
+
+fi
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+ # TEA specific: for combined 32 & 64 bit fat builds of Tk
+ # extensions, verify that 64-bit build is possible.
+ if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"; then :
+
+ if test "${TEA_WINDOWINGSYSTEM}" = x11; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5
+$as_echo_n "checking for 64-bit X11... " >&6; }
+if ${tcl_cv_lib_x11_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
+ LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
+ 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 :
+ tcl_cv_lib_x11_64=yes
+else
+ tcl_cv_lib_x11_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5
+$as_echo "$tcl_cv_lib_x11_64" >&6; }
+
+fi
+ if test "${TEA_WINDOWINGSYSTEM}" = aqua; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5
+$as_echo_n "checking for 64-bit Tk... " >&6; }
+if ${tcl_cv_lib_tk_64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
+ LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <tk.h>
+int
+main ()
+{
+Tk_InitStubs(NULL, "", 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_lib_tk_64=yes
+else
+ tcl_cv_lib_tk_64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5
+$as_echo "$tcl_cv_lib_tk_64" >&6; }
+
+fi
+ # remove 64-bit arch flags from CFLAGS et al. if configuration
+ # does not support 64-bit.
+ if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5
+$as_echo "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;}
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done
+fi
+
+fi
+ ;;
+ OS/390-*)
+ CFLAGS_OPTIMIZE="" # Optimizer is buggy
+
+$as_echo "#define _OE_SOCKETS 1" >>confdefs.h
+
+ ;;
+ OSF1-V*)
+ # Digital OSF/1
+ SHLIB_CFLAGS=""
+ if test "$SHARED_BUILD" = 1; then :
+
+ SHLIB_LD='ld -shared -expect_unresolved "*"'
+
+else
+
+ SHLIB_LD='ld -non_shared -expect_unresolved "*"'
+
+fi
+ SHLIB_SUFFIX=".so"
+ if test $doRpath = yes; then :
+
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'
+fi
+ if test "$GCC" = yes; then :
+ CFLAGS="$CFLAGS -mieee"
+else
+
+ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"
+fi
+ # see pthread_intro(3) for pthread support on osf1, k.furukawa
+ if test "${TCL_THREADS}" = 1; then :
+
+ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
+ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
+ LIBS=`echo $LIBS | sed s/-lpthreads//`
+ if test "$GCC" = yes; then :
+
+ LIBS="$LIBS -lpthread -lmach -lexc"
+
+else
+
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+
+fi
+
+fi
+ ;;
+ QNX-6*)
+ # QNX RTP
+ # This may work for all QNX, but it was only reported for v6.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="ld -Bshareable -x"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SCO_SV-3.2*)
+ if test "$GCC" = yes; then :
+
+ SHLIB_CFLAGS="-fPIC -melf"
+ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
+
+else
+
+ SHLIB_CFLAGS="-Kpic -belf"
+ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+
+fi
+ SHLIB_LD="ld -G"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SunOS-5.[0-6])
+ # Careful to not let 5.10+ fall into this case
+
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_SUFFIX=".so"
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+else
+
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+
+fi
+ ;;
+ SunOS-5*)
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+
+$as_echo "#define _REENTRANT 1" >>confdefs.h
+
+
+$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h
+
+
+ SHLIB_CFLAGS="-KPIC"
+
+ # Check to enable 64-bit flags for compiler/linker
+ if test "$do64bit" = yes; then :
+
+ arch=`isainfo`
+ if test "$arch" = "sparcv9 sparc"; then :
+
+ if test "$GCC" = yes; then :
+
+ if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;}
+
+else
+
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+
+fi
+
+else
+
+ do64bit_ok=yes
+ if test "$do64bitVIS" = yes; then :
+
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+
+else
+
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+
+fi
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+
+fi
+
+else
+ if test "$arch" = "amd64 i386"; then :
+
+ if test "$GCC" = yes; then :
+
+ case $system in
+ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};;
+ esac
+
+else
+
+ do64bit_ok=yes
+ case $system in
+ SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*)
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ CFLAGS="$CFLAGS -xarch=amd64"
+ LDFLAGS="$LDFLAGS -xarch=amd64";;
+ esac
+
+fi
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5
+$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;}
+fi
+fi
+
+fi
+
+ SHLIB_SUFFIX=".so"
+ if test "$GCC" = yes; then :
+
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ if test "$do64bit_ok" = yes; then :
+
+ if test "$arch" = "sparcv9 sparc"; then :
+
+ # We need to specify -static-libgcc or we need to
+ # add the path to the sparv9 libgcc.
+ # JH: static-libgcc is necessary for core Tcl, but may
+ # not be necessary for extensions.
+ SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
+ # for finding sparcv9 libgcc, get the regular libgcc
+ # path, remove so name and append 'sparcv9'
+ #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
+ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
+
+else
+ if test "$arch" = "amd64 i386"; then :
+
+ # JH: static-libgcc is necessary for core Tcl, but may
+ # not be necessary for extensions.
+ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
+
+fi
+fi
+
+fi
+
+else
+
+ case $system in
+ SunOS-5.[1-9][0-9]*)
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';;
+ *)
+ SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
+ esac
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+
+fi
+ ;;
+ UNIX_SV* | UnixWare-5*)
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
+ # that don't grok the -Bexport option. Test that it does.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5
+$as_echo_n "checking for ld accepts -Bexport flag... " >&6; }
+if ${tcl_cv_ld_Bexport+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ tcl_cv_ld_Bexport=yes
+else
+ tcl_cv_ld_Bexport=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS=$hold_ldflags
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5
+$as_echo "$tcl_cv_ld_Bexport" >&6; }
+ if test $tcl_cv_ld_Bexport = yes; then :
+
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+
+fi
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ esac
+
+ if test "$do64bit" = yes -a "$do64bit_ok" = no; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5
+$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;}
+
+fi
+
+
+
+ # Add in the arch flags late to ensure it wasn't removed.
+ # Not necessary in TEA, but this is aligned with core
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
+
+ # If we're running gcc, then change the C flags for compiling shared
+ # libraries to the right flags for gcc, instead of those for the
+ # standard manufacturer compiler.
+
+ if test "$GCC" = yes; then :
+
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*|MINGW32_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ windows) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac
+fi
+
+ if test "$tcl_cv_cc_visibility_hidden" != yes; then :
+
+
+$as_echo "#define MODULE_SCOPE extern" >>confdefs.h
+
+
+fi
+
+ if test "$SHARED_LIB_SUFFIX" = ""; then :
+
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'
+fi
+ if test "$UNSHARED_LIB_SUFFIX" = ""; then :
+
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'
+fi
+
+ if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5
+$as_echo_n "checking for SEH support in compiler... " >&6; }
+if ${tcl_cv_seh+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ tcl_cv_seh=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+ int main(int argc, char** argv) {
+ int a, b = 0;
+ __try {
+ a = 666 / b;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ return 0;
+ }
+ return 1;
+ }
+
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ tcl_cv_seh=yes
+else
+ tcl_cv_seh=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
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5
+$as_echo "$tcl_cv_seh" >&6; }
+ if test "$tcl_cv_seh" = "no" ; then
+
+$as_echo "#define HAVE_NO_SEH 1" >>confdefs.h
+
+ fi
+
+ #
+ # Check to see if the excpt.h include file provided contains the
+ # definition for EXCEPTION_DISPOSITION; if not, which is the case
+ # with Cygwin's version as of 2002-04-10, define it to be int,
+ # sufficient for getting the current code to work.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5
+$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; }
+if ${tcl_cv_eh_disposition+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+
+int
+main ()
+{
+
+ EXCEPTION_DISPOSITION x;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_eh_disposition=yes
+else
+ tcl_cv_eh_disposition=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5
+$as_echo "$tcl_cv_eh_disposition" >&6; }
+ if test "$tcl_cv_eh_disposition" = "no" ; then
+
+$as_echo "#define EXCEPTION_DISPOSITION int" >>confdefs.h
+
+ fi
+
+ # Check to see if winnt.h defines CHAR, SHORT, and LONG
+ # even if VOID has already been #defined. The win32api
+ # used by mingw and cygwin is known to do this.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5
+$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; }
+if ${tcl_cv_winnt_ignore_void+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#define VOID void
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+int
+main ()
+{
+
+ CHAR c;
+ SHORT s;
+ LONG l;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_winnt_ignore_void=yes
+else
+ tcl_cv_winnt_ignore_void=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5
+$as_echo "$tcl_cv_winnt_ignore_void" >&6; }
+ if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
+
+$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h
+
+ fi
+ fi
+
+ # See if the compiler supports casting to a union type.
+ # This is used to stop gcc from printing a compiler
+ # warning when initializing a union member.
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5
+$as_echo_n "checking for cast to union support... " >&6; }
+if ${tcl_cv_cast_to_union+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ union foo { int i; double d; };
+ union foo f = (union foo) (int) 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_cast_to_union=yes
+else
+ tcl_cv_cast_to_union=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5
+$as_echo "$tcl_cv_cast_to_union" >&6; }
+ if test "$tcl_cv_cast_to_union" = "yes"; then
+
+$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h
+
+ fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # These must be called after we do the basic CFLAGS checks and
+ # verify any possible 64-bit or similar switches are necessary
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5
+$as_echo_n "checking for required early compiler flags... " >&6; }
+ tcl_flags=""
+
+ if ${tcl_cv_flag__isoc99_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+int
+main ()
+{
+char *p = (char *)strtoll; char *q = (char *)strtoull;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__isoc99_source=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _ISOC99_SOURCE 1
+#include <stdlib.h>
+int
+main ()
+{
+char *p = (char *)strtoll; char *q = (char *)strtoull;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__isoc99_source=yes
+else
+ tcl_cv_flag__isoc99_source=no
+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
+
+ if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then
+
+$as_echo "#define _ISOC99_SOURCE 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _ISOC99_SOURCE"
+ fi
+
+
+ if ${tcl_cv_flag__largefile64_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 buf; int i = stat64("/", &buf);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile64_source=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGEFILE64_SOURCE 1
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 buf; int i = stat64("/", &buf);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile64_source=yes
+else
+ tcl_cv_flag__largefile64_source=no
+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
+
+ if test "x${tcl_cv_flag__largefile64_source}" = "xyes" ; then
+
+$as_echo "#define _LARGEFILE64_SOURCE 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _LARGEFILE64_SOURCE"
+ fi
+
+
+ if ${tcl_cv_flag__largefile_source64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+char *p = (char *)open64;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile_source64=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGEFILE_SOURCE64 1
+#include <sys/stat.h>
+int
+main ()
+{
+char *p = (char *)open64;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_flag__largefile_source64=yes
+else
+ tcl_cv_flag__largefile_source64=no
+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
+
+ if test "x${tcl_cv_flag__largefile_source64}" = "xyes" ; then
+
+$as_echo "#define _LARGEFILE_SOURCE64 1" >>confdefs.h
+
+ tcl_flags="$tcl_flags _LARGEFILE_SOURCE64"
+ fi
+
+ if test "x${tcl_flags}" = "x" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5
+$as_echo "none" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5
+$as_echo "${tcl_flags}" >&6; }
+ fi
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5
+$as_echo_n "checking for 64-bit integer type... " >&6; }
+ if ${tcl_cv_type_64bit+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ tcl_cv_type_64bit=none
+ # See if the compiler knows natively about __int64
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+__int64 value = (__int64) 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_type_64bit=__int64
+else
+ tcl_type_64bit="long long"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ # See if we should use long anyway Note that we substitute in the
+ # type that is our current guess for a 64-bit type inside this check
+ # program, so it should be modified only carefully...
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+switch (0) {
+ case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ;
+ }
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_64bit=${tcl_type_64bit}
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "${tcl_cv_type_64bit}" = none ; then
+
+$as_echo "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using long" >&5
+$as_echo "using long" >&6; }
+ elif test "${tcl_cv_type_64bit}" = "__int64" \
+ -a "${TEA_PLATFORM}" = "windows" ; then
+ # TEA specific: We actually want to use the default tcl.h checks in
+ # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5
+$as_echo "using Tcl header defaults" >&6; }
+ else
+
+cat >>confdefs.h <<_ACEOF
+#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5
+$as_echo "${tcl_cv_type_64bit}" >&6; }
+
+ # Now check for auxiliary declarations
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5
+$as_echo_n "checking for struct dirent64... " >&6; }
+if ${tcl_cv_struct_dirent64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <dirent.h>
+int
+main ()
+{
+struct dirent64 p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_struct_dirent64=yes
+else
+ tcl_cv_struct_dirent64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5
+$as_echo "$tcl_cv_struct_dirent64" >&6; }
+ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5
+$as_echo_n "checking for struct stat64... " >&6; }
+if ${tcl_cv_struct_stat64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/stat.h>
+int
+main ()
+{
+struct stat64 p;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_struct_stat64=yes
+else
+ tcl_cv_struct_stat64=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5
+$as_echo "$tcl_cv_struct_stat64" >&6; }
+ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
+
+$as_echo "#define HAVE_STRUCT_STAT64 1" >>confdefs.h
+
+ fi
+
+ for ac_func in open64 lseek64
+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
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5
+$as_echo_n "checking for off64_t... " >&6; }
+ if ${tcl_cv_type_off64_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+off64_t offset;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ tcl_cv_type_off64_t=yes
+else
+ tcl_cv_type_off64_t=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ if test "x${tcl_cv_type_off64_t}" = "xyes" && \
+ test "x${ac_cv_func_lseek64}" = "xyes" && \
+ test "x${ac_cv_func_open64}" = "xyes" ; then
+
+$as_echo "#define HAVE_TYPE_OFF64_T 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
+ fi
+
+
+
+#--------------------------------------------------------------------
+# Set the default compiler switches based on the --enable-symbols option.
+#--------------------------------------------------------------------
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5
+$as_echo_n "checking for build with symbols... " >&6; }
+ # Check whether --enable-symbols was given.
+if test "${enable_symbols+set}" = set; then :
+ enableval=$enable_symbols; tcl_ok=$enableval
+else
+ tcl_ok=no
+fi
+
+ DBGX=""
+ if test "$tcl_ok" = "no"; then
+ CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
+ LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ else
+ CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
+ LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
+ if test "$tcl_ok" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5
+$as_echo "yes (standard debugging)" >&6; }
+ fi
+ fi
+ # TEA specific:
+ if test "${TEA_PLATFORM}" != "windows" ; then
+ LDFLAGS_DEFAULT="${LDFLAGS}"
+ fi
+
+
+
+
+ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
+
+$as_echo "#define TCL_MEM_DEBUG 1" >>confdefs.h
+
+ fi
+
+ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+ if test "$tcl_ok" = "all"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5
+$as_echo "enabled symbols mem debugging" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5
+$as_echo "enabled $tcl_ok debugging" >&6; }
+ fi
+ fi
+
+
+#--------------------------------------------------------------------
+# Everyone should be linking against the Tcl stub library. If you
+# can't for some reason, remove this definition. If you aren't using
+# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
+# link against the non-stubbed Tcl library. Add Tk too if necessary.
+#--------------------------------------------------------------------
+
+
+$as_echo "#define USE_TCL_STUBS 1" >>confdefs.h
+
+
+$as_echo "#define USE_TK_STUBS 1" >>confdefs.h
+
+
+#--------------------------------------------------------------------
+# This macro generates a line to use when building a library. It
+# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
+# and TEA_LOAD_TCLCONFIG macros above.
+#--------------------------------------------------------------------
+
+
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
+ MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS)"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+print("manifest needed")
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "manifest needed" >/dev/null 2>&1; then :
+
+ # Could do a CHECK_PROG for mt, but should always be with MSVC8+
+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi"
+ VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi"
+ MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
+
+ CLEANFILES="$CLEANFILES *.manifest"
+
+
+fi
+rm -f conftest*
+
+ MAKE_STUB_LIB="\${STLIB_LD} -out:\$@ \$(PKG_STUB_OBJECTS)"
+ else
+ MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
+ MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)"
+ fi
+
+ if test "${SHARED_BUILD}" = "1" ; then
+ MAKE_LIB="${MAKE_SHARED_LIB} "
+ else
+ MAKE_LIB="${MAKE_STATIC_LIB} "
+ fi
+
+ #--------------------------------------------------------------------
+ # Shared libraries and static libraries have different names.
+ # Use the double eval to make sure any variables in the suffix is
+ # substituted. (@@@ Might not be necessary anymore)
+ #--------------------------------------------------------------------
+
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ if test "${SHARED_BUILD}" = "1" ; then
+ # We force the unresolved linking of symbols that are really in
+ # the private libraries of Tcl and Tk.
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
+ if test x"${TK_BIN_DIR}" != x ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
+ fi
+ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ else
+ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+ fi
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ if test "$GCC" = "yes"; then
+ PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
+ fi
+ # These aren't needed on Windows (either MSVC or gcc)
+ RANLIB=:
+ RANLIB_STUB=:
+ else
+ RANLIB_STUB="${RANLIB}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
+ if test x"${TK_BIN_DIR}" != x ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
+ fi
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ RANLIB=:
+ else
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+ fi
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ fi
+
+ # These are escaped so that only CFLAGS is picked up at configure time.
+ # The other values will be substituted at make time.
+ CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
+ fi
+
+
+
+
+
+
+
+
+
+
+#--------------------------------------------------------------------
+# Locate the X11 header files and the X11 library archive.
+#--------------------------------------------------------------------
+
+
+ { $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
+
+ not_really_there=""
+ if test "$no_x" = ""; then
+ if test "$x_includes" = ""; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/XIntrinsic.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ not_really_there="yes"
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ else
+ if test ! -r $x_includes/X11/Intrinsic.h; then
+ not_really_there="yes"
+ fi
+ fi
+ fi
+ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 header files" >&5
+$as_echo_n "checking for X11 header files... " >&6; }
+ found_xincludes="no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <X11/Intrinsic.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ found_xincludes="yes"
+else
+ found_xincludes="no"
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+ if test "$found_xincludes" = "no"; then
+ dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
+ for i in $dirs ; do
+ if test -r $i/X11/Intrinsic.h; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5
+$as_echo "$i" >&6; }
+ XINCLUDES=" -I$i"
+ found_xincludes="yes"
+ break
+ fi
+ done
+ fi
+ else
+ if test "$x_includes" != ""; then
+ XINCLUDES="-I$x_includes"
+ found_xincludes="yes"
+ fi
+ fi
+ if test "$found_xincludes" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: couldn't find any!" >&5
+$as_echo "couldn't find any!" >&6; }
+ fi
+
+ if test "$no_x" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X11 libraries" >&5
+$as_echo_n "checking for X11 libraries... " >&6; }
+ XLIBSW=nope
+ dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
+ for i in $dirs ; do
+ if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $i" >&5
+$as_echo "$i" >&6; }
+ XLIBSW="-L$i -lX11"
+ x_libraries="$i"
+ break
+ fi
+ done
+ else
+ if test "$x_libraries" = ""; then
+ XLIBSW=-lX11
+ else
+ XLIBSW="-L$x_libraries -lX11"
+ fi
+ fi
+ if test "$XLIBSW" = nope ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XCreateWindow in -lXwindow" >&5
+$as_echo_n "checking for XCreateWindow in -lXwindow... " >&6; }
+if ${ac_cv_lib_Xwindow_XCreateWindow+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXwindow $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 XCreateWindow ();
+int
+main ()
+{
+return XCreateWindow ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xwindow_XCreateWindow=yes
+else
+ ac_cv_lib_Xwindow_XCreateWindow=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_Xwindow_XCreateWindow" >&5
+$as_echo "$ac_cv_lib_Xwindow_XCreateWindow" >&6; }
+if test "x$ac_cv_lib_Xwindow_XCreateWindow" = xyes; then :
+ XLIBSW=-lXwindow
+fi
+
+ fi
+ if test "$XLIBSW" = nope ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: could not find any! Using -lX11." >&5
+$as_echo "could not find any! Using -lX11." >&6; }
+ XLIBSW=-lX11
+ fi
+
+
+#--------------------------------------------------------------------
+# Check for freetype / fontconfig / Xft support.
+#--------------------------------------------------------------------
+
+if test "${TEA_WINDOWINGSYSTEM}" = "x11"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use xft" >&5
+$as_echo_n "checking whether to use xft... " >&6; }
+ # Check whether --enable-xft was given.
+if test "${enable_xft+set}" = set; then :
+ enableval=$enable_xft; enable_xft=$enableval
+else
+ enable_xft="default"
+fi
+
+ XFT_CFLAGS=""
+ XFT_LIBS=""
+ if test "$enable_xft" = "no" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_xft" >&5
+$as_echo "$enable_xft" >&6; }
+ else
+ found_xft="yes"
+ XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
+ if test "$found_xft" = "no" ; then
+ found_xft=yes
+ XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_xft" >&5
+$as_echo "$found_xft" >&6; }
+ if test "$found_xft" = "yes" ; then
+ tk_oldCFlags=$CFLAGS
+ CFLAGS="$XINCLUDES $XFT_CFLAGS"
+ tk_oldLibs=$LIBS
+ LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
+ ac_fn_c_check_header_compile "$LINENO" "X11/Xft/Xft.h" "ac_cv_header_X11_Xft_Xft_h" "#include <X11/Xlib.h>
+"
+if test "x$ac_cv_header_X11_Xft_Xft_h" = xyes; then :
+
+else
+
+ found_xft=no
+
+fi
+
+
+ CFLAGS=$tk_oldCFlags
+ LIBS=$tk_oldLibs
+ fi
+ if test "$found_xft" = "yes" ; then
+ tk_oldCFlags=$CFLAGS
+ CFLAGS="$XINCLUDES $XFT_CFLAGS"
+ tk_oldLibs=$LIBS
+ LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XftFontOpen in -lXft" >&5
+$as_echo_n "checking for XftFontOpen in -lXft... " >&6; }
+if ${ac_cv_lib_Xft_XftFontOpen+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lXft $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 XftFontOpen ();
+int
+main ()
+{
+return XftFontOpen ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_Xft_XftFontOpen=yes
+else
+ ac_cv_lib_Xft_XftFontOpen=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_Xft_XftFontOpen" >&5
+$as_echo "$ac_cv_lib_Xft_XftFontOpen" >&6; }
+if test "x$ac_cv_lib_Xft_XftFontOpen" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXFT 1
+_ACEOF
+
+ LIBS="-lXft $LIBS"
+
+else
+
+ found_xft=no
+
+fi
+
+ CFLAGS=$tk_oldCFlags
+ LIBS=$tk_oldLibs
+ fi
+ if test "$found_xft" = "no" ; then
+ if test "$enable_xft" = "yes" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find xft configuration, or xft is unusable" >&5
+$as_echo "$as_me: WARNING: Can't find xft configuration, or xft is unusable" >&2;}
+ fi
+ enable_xft=no
+ XFT_CFLAGS=""
+ XFT_LIBS=""
+ else
+ enable_xft=yes
+ fi
+ fi
+ if test $enable_xft = "yes" ; then
+
+$as_echo "#define HAVE_XFT 1" >>confdefs.h
+
+ fi
+
+
+fi
+
+#--------------------------------------------------------------------
+# Determine the name of the tclsh and/or wish executables in the
+# Tcl and Tk build directories or the location they were installed
+# into. These paths are used to support running test cases only,
+# the Makefile should not be making use of these paths to generate
+# a pkgIndex.tcl file or anything else at extension build time.
+#--------------------------------------------------------------------
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5
+$as_echo_n "checking for tclsh... " >&6; }
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ # tclConfig.sh is in Tcl build directory
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
+ else
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
+ fi
+ else
+ # tclConfig.sh is in install location
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
+ else
+ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
+ fi
+ list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`"
+ for i in $list ; do
+ if test -f "$i/${TCLSH_PROG}" ; then
+ REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
+ break
+ fi
+ done
+ TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5
+$as_echo "${TCLSH_PROG}" >&6; }
+
+
+#TEA_PROG_WISH
+
+#--------------------------------------------------------------------
+# Finally, substitute all of the various values into the Makefile.
+# You may alternatively have a special pkgIndex.tcl.in or other files
+# which require substituting th AC variables in. Include these here.
+#--------------------------------------------------------------------
+
+ac_config_files="$ac_config_files 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
+
+
+
+CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""
+
+: "${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 -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+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
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# 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 tlt $as_me 3.0, which was
+generated by GNU Autoconf 2.69. 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"
+
+_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
+
+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="\\
+tlt config.status 3.0
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 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'
+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
+_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
+ "Makefile") CONFIG_FILES="$CONFIG_FILES 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
+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 "
+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
+ #
+
+_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
+$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
+ ;;
+
+
+
+ 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/tlt3.0/configure.in b/tlt3.0/configure.in
new file mode 100755
index 0000000..bfa0d48
--- /dev/null
+++ b/tlt3.0/configure.in
@@ -0,0 +1,299 @@
+#!/bin/bash -norc
+dnl This file is an input file used by the GNU "autoconf" program to
+dnl generate the file "configure", which is run during Tcl installation
+dnl to configure the system for the local environment.
+
+#-----------------------------------------------------------------------
+# Sample configure.in for Tcl Extensions. The only places you should
+# need to modify this file are marked by the string __CHANGE__
+#-----------------------------------------------------------------------
+
+#-----------------------------------------------------------------------
+# __CHANGE__
+# Set your package name and version numbers here.
+#
+# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
+# set as provided. These will also be added as -D defs in your Makefile
+# so you can encode the package version directly into the source files.
+# This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME>
+# so that we create the export library with the dll.
+#-----------------------------------------------------------------------
+
+AC_INIT([tlt], [3.0])
+
+#--------------------------------------------------------------------
+# Call TEA_INIT as the first TEA_ macro to set up initial vars.
+# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
+# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
+#--------------------------------------------------------------------
+
+TEA_INIT([3.9])
+
+AC_CONFIG_AUX_DIR(tclconfig)
+
+#--------------------------------------------------------------------
+# Load the tclConfig.sh file
+#--------------------------------------------------------------------
+
+TEA_PATH_TCLCONFIG
+TEA_LOAD_TCLCONFIG
+
+#--------------------------------------------------------------------
+# Load the tkConfig.sh file if necessary (Tk extension)
+#--------------------------------------------------------------------
+
+TEA_PATH_TKCONFIG
+TEA_LOAD_TKCONFIG
+
+#-----------------------------------------------------------------------
+# Handle the --prefix=... option by defaulting to what Tcl gave.
+# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
+#-----------------------------------------------------------------------
+
+TEA_PREFIX
+
+#-----------------------------------------------------------------------
+# Standard compiler checks.
+# This sets up CC by using the CC env var, or looks for gcc otherwise.
+# This also calls AC_PROG_CC and a few others to create the basic setup
+# necessary to compile executables.
+#-----------------------------------------------------------------------
+
+TEA_SETUP_COMPILER
+
+#-----------------------------------------------------------------------
+# __CHANGE__
+# Specify the C source files to compile in TEA_ADD_SOURCES,
+# public headers that need to be installed in TEA_ADD_HEADERS,
+# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
+# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
+# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
+# and PKG_TCL_SOURCES.
+#-----------------------------------------------------------------------
+TEA_ADD_SOURCES([
+ bltBase64.c
+ bltBgStyle.c
+ bltBind.c
+ bltBitmap.c
+ bltChain.c
+ bltConfig.c
+ bltDBuffer.c
+ bltGrAxis.c
+ bltGrBar.c
+ bltGrElem.c
+ bltGrHairs.c
+ bltGrLegd.c
+ bltGrLine.c
+ bltGrMarker.c
+ bltGrMisc.c
+ bltGrPen.c
+ bltGrPs.c
+ bltGraph.c
+ bltHash.c
+ bltImage.c
+ bltInt.c
+ bltInit.c
+ bltList.c
+ bltNsUtil.c
+ bltParse.c
+ bltPool.c
+ bltPs.c
+ bltPsAfm.c
+ bltSpline.c
+ bltSwitch.c
+ bltText.c
+ bltUnixFont.c
+ bltUnixWindow.c
+ bltUtil.c
+ bltVecCmd.c
+ bltVecMath.c
+ bltVector.c
+ bltWindow.c
+ ])
+TEA_ADD_HEADERS([bltVector.h])
+TEA_ADD_INCLUDES([-I. -I\"`${CYGPATH} ${srcdir}`\"])
+TEA_ADD_LIBS([])
+TEA_ADD_CFLAGS([-Wunused])
+TEA_ADD_STUB_SOURCES([])
+TEA_ADD_TCL_SOURCES([library/graph.tcl library/bltGraph.pro])
+
+#--------------------------------------------------------------------
+# __CHANGE__
+#
+# You can add more files to clean if your extension creates any extra
+# files by extending CLEANFILES.
+# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
+# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
+#
+# A few miscellaneous platform-specific items:
+# TEA_ADD_* any platform specific compiler/build info here.
+#--------------------------------------------------------------------
+
+CLEANFILES="$CLEANFILES config.status config.log Makefile"
+if test "${TEA_PLATFORM}" = "windows" ; then
+ # Ensure no empty if clauses
+ :
+ #TEA_ADD_SOURCES([win/winFile.c])
+ #TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
+else
+ # Ensure no empty else clauses
+ :
+ #TEA_ADD_SOURCES([unix/unixFile.c])
+ #TEA_ADD_LIBS([-lsuperfly])
+fi
+
+#--------------------------------------------------------------------
+# __CHANGE__
+# Choose which headers you need. Extension authors should try very
+# hard to only rely on the Tcl public header files. Internal headers
+# contain private data structures and are subject to change without
+# notice.
+# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
+#--------------------------------------------------------------------
+
+TEA_PUBLIC_TCL_HEADERS
+TEA_PRIVATE_TCL_HEADERS
+
+TEA_PUBLIC_TK_HEADERS
+TEA_PRIVATE_TK_HEADERS
+#TEA_PATH_X
+
+#--------------------------------------------------------------------
+# Check whether --enable-threads or --disable-threads was given.
+# This auto-enables if Tcl was compiled threaded.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_THREADS
+
+#--------------------------------------------------------------------
+# The statement below defines a collection of symbols related to
+# building as a shared library instead of a static library.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_SHARED
+
+#--------------------------------------------------------------------
+# This macro figures out what flags to use with the compiler/linker
+# when building shared/static debug/optimized objects. This information
+# can be taken from the tclConfig.sh file, but this figures it all out.
+#--------------------------------------------------------------------
+
+TEA_CONFIG_CFLAGS
+
+#--------------------------------------------------------------------
+# Set the default compiler switches based on the --enable-symbols option.
+#--------------------------------------------------------------------
+
+TEA_ENABLE_SYMBOLS
+
+#--------------------------------------------------------------------
+# Everyone should be linking against the Tcl stub library. If you
+# can't for some reason, remove this definition. If you aren't using
+# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
+# link against the non-stubbed Tcl library. Add Tk too if necessary.
+#--------------------------------------------------------------------
+
+AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
+AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
+
+#--------------------------------------------------------------------
+# This macro generates a line to use when building a library. It
+# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
+# and TEA_LOAD_TCLCONFIG macros above.
+#--------------------------------------------------------------------
+
+TEA_MAKE_LIB
+
+#--------------------------------------------------------------------
+# Locate the X11 header files and the X11 library archive.
+#--------------------------------------------------------------------
+
+SC_PATH_X
+
+#--------------------------------------------------------------------
+# Check for freetype / fontconfig / Xft support.
+#--------------------------------------------------------------------
+
+if test "${TEA_WINDOWINGSYSTEM}" = "x11"; then
+ AC_MSG_CHECKING([whether to use xft])
+ AC_ARG_ENABLE(xft,
+ AC_HELP_STRING([--enable-xft],
+ [use freetype/fontconfig/xft (default: on)]),
+ [enable_xft=$enableval], [enable_xft="default"])
+ XFT_CFLAGS=""
+ XFT_LIBS=""
+ if test "$enable_xft" = "no" ; then
+ AC_MSG_RESULT([$enable_xft])
+ else
+ found_xft="yes"
+ dnl make sure package configurator (xft-config or pkg-config
+ dnl says that xft is present.
+ XFT_CFLAGS=`xft-config --cflags 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`xft-config --libs 2>/dev/null` || found_xft="no"
+ if test "$found_xft" = "no" ; then
+ found_xft=yes
+ XFT_CFLAGS=`pkg-config --cflags xft 2>/dev/null` || found_xft="no"
+ XFT_LIBS=`pkg-config --libs xft 2>/dev/null` || found_xft="no"
+ fi
+ AC_MSG_RESULT([$found_xft])
+ dnl make sure that compiling against Xft header file doesn't bomb
+ if test "$found_xft" = "yes" ; then
+ tk_oldCFlags=$CFLAGS
+ CFLAGS="$XINCLUDES $XFT_CFLAGS"
+ tk_oldLibs=$LIBS
+ LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
+ AC_CHECK_HEADER(X11/Xft/Xft.h, [], [
+ found_xft=no
+ ],[#include <X11/Xlib.h>])
+ CFLAGS=$tk_oldCFlags
+ LIBS=$tk_oldLibs
+ fi
+ dnl make sure that linking against Xft libraries finds freetype
+ if test "$found_xft" = "yes" ; then
+ tk_oldCFlags=$CFLAGS
+ CFLAGS="$XINCLUDES $XFT_CFLAGS"
+ tk_oldLibs=$LIBS
+ LIBS="$tk_oldLIBS $XFT_LIBS $XLIBSW"
+ AC_CHECK_LIB(Xft, XftFontOpen, [], [
+ found_xft=no
+ ])
+ CFLAGS=$tk_oldCFlags
+ LIBS=$tk_oldLibs
+ fi
+ dnl print a warning if xft is unusable and was specifically requested
+ if test "$found_xft" = "no" ; then
+ if test "$enable_xft" = "yes" ; then
+ AC_MSG_WARN([Can't find xft configuration, or xft is unusable])
+ fi
+ enable_xft=no
+ XFT_CFLAGS=""
+ XFT_LIBS=""
+ else
+ enable_xft=yes
+ fi
+ fi
+ if test $enable_xft = "yes" ; then
+ AC_DEFINE(HAVE_XFT, 1, [Have we turned on XFT (antialiased fonts)?])
+ fi
+ AC_SUBST(XFT_CFLAGS)
+ AC_SUBST(XFT_LIBS)
+fi
+
+#--------------------------------------------------------------------
+# Determine the name of the tclsh and/or wish executables in the
+# Tcl and Tk build directories or the location they were installed
+# into. These paths are used to support running test cases only,
+# the Makefile should not be making use of these paths to generate
+# a pkgIndex.tcl file or anything else at extension build time.
+#--------------------------------------------------------------------
+
+TEA_PROG_TCLSH
+#TEA_PROG_WISH
+
+#--------------------------------------------------------------------
+# Finally, substitute all of the various values into the Makefile.
+# You may alternatively have a special pkgIndex.tcl.in or other files
+# which require substituting th AC variables in. Include these here.
+#--------------------------------------------------------------------
+
+AC_OUTPUT([Makefile])
diff --git a/tlt3.0/doc/BLT.n b/tlt3.0/doc/BLT.n
new file mode 100644
index 0000000..1593029
--- /dev/null
+++ b/tlt3.0/doc/BLT.n
@@ -0,0 +1,153 @@
+'\"
+'\" Copyright 1991-1997 by Bell Labs Innovations for Lucent Technologies.
+'\"
+'\" 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 the
+'\" copyright notice and warranty disclaimer appear in supporting documentation,
+'\" and that the names of Lucent Technologies any of their entities not be used
+'\" in advertising or publicity pertaining to distribution of the software
+'\" without specific, written prior permission.
+'\"
+'\" Lucent Technologies disclaims all warranties with regard to this software,
+'\" including all implied warranties of merchantability and fitness. In no event
+'\" shall Lucent Technologies 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
+'\" tortuous action, arising out of or in connection with the use or performance
+'\" of this software.
+'\"
+.so man.macros
+.TH intro n BLT_VERSION BLT "BLT Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+BLT \- Introduction to the BLT library
+.BE
+.SH DESCRIPTION
+BLT is a library of extensions to the Tk library. It adds new
+commands and variables to the application's interpreter.
+.LP
+.SH COMMANDS
+The following commands are added to the interpreter from the BLT library:
+.TP 15
+\fBtable\fR
+A table geometry manager for Tk. You specify window placements as table
+row,column positions and windows can also span multiple rows or columns.
+It also has many options for setting and/or bounding window sizes.
+.TP 15
+\fBgraph\fR
+A 2D plotting widget. Plots two variable data in a window with an optional
+legend and annotations. It has of several components; coordinate axes,
+crosshairs, a legend, and a collection of elements and tags.
+.TP 15
+\fBbarchart\fR
+A barchart widget. Plots two-variable data as rectangular bars in a
+window. The x-coordinate values designate the position of the bar along
+the x-axis, while the y-coordinate values designate the magnitude.
+The \fBbarchart\fR widget has of several components; coordinate axes,
+crosshairs, a legend, and a collection of elements and tags.
+.TP 15
+\fBvector\fR
+Creates a vector of floating point values. The vector's components
+can be manipulated in three ways: through a Tcl array variable, a Tcl
+command, or the C API.
+.TP
+\fBspline\fR
+Computes a spline fitting a set of data points (x and y vectors) and
+produces a vector of the interpolated images (y-coordinates) at a
+given set of x-coordinates.
+.TP 15
+\fBbgexec\fR
+Like Tcl's \fBexec\fR command, \fBbgexec\fR runs a pipeline of Unix
+commands in the background. Unlike \fBexec\fR, the output of the last
+process is collected and a global Tcl variable is set upon its completion.
+\fBbgexec\fR can be used with \fBtkwait\fR to wait for Unix commands
+to finish while still handling expose events. Intermediate output is
+also available while the pipeline is active.
+.TP 15
+\fBbusy\fR
+Creates a "busy window" which prevents user-interaction when an
+application is busy. The busy window also provides an easy way
+to have temporary busy cursors (such as a watch or hourglass).
+.TP 15
+\fBbitmap\fR
+Reads and writes bitmaps from Tcl. New X bitmaps can be defined
+on-the-fly from Tcl, obviating the need to copy around bitmap files.
+Other options query loaded X bitmap's dimensions and data.
+.TP 15
+\fBdrag&drop\fR
+Provides a drag-and-drop facility for Tk. Information (represented
+by a token window) can be dragged to and from any Tk window, including
+those of another Tk application. \fBdrag&drop\fR acts as a
+coordinator, directing Tk \fBsend\fR commands between (or within) TCL/Tk
+applications.
+.TP 15
+\fBhtext\fR
+A simple hypertext widget. Combines text and Tk widgets into a single
+scroll-able window. Tcl commands can be embedded into text, which are
+invoked as the text is parsed. In addition, Tk widgets can be
+appended to the window at the current point in the text. \fBHtext\fR
+can be also used to create scrolled windows of Tk widgets.
+.TP 15
+\fBwinop\fR
+Raise, lower, map, or, unmap any window. The raise and lower functions
+are useful for stacking windows above or below "busy windows".
+.TP 15
+\fBwatch\fR
+Arranges for Tcl procedures to be called before and/or after the execution
+of every Tcl command. This command
+may be used in the logging, profiling, or tracing of Tcl code.
+.TP 15
+\fBbltdebug\fR
+A simple Tcl command tracing facility useful for debugging Tcl code.
+Displays each Tcl command before and after substitution along its level
+in the interpreter on standard error.
+.SH VARIABLES
+.PP
+The following Tcl variables are either set or used by BLT at various times
+in its execution:
+.TP 15
+\fBblt_library\fR
+This variable contains the name of a directory containing a library
+of Tcl scripts and other files related to BLT. Currently, this
+directory contains the \fBdrag&drop\fR protocol scripts and the
+PostScript prolog
+used by \fBgraph\fR and \fBbarchart\fR.
+The value of this variable is taken from the BLT_LIBRARY environment
+variable, if one exists, or else from a default value compiled into
+the \fBBLT\fR library.
+.TP 15
+\fBblt_versions\fR
+This variable is set in the interpreter for each application. It is an
+array of the current version numbers for each
+of the BLT commands in the form \fImajor\fR.\fIminor\fR. \fIMajor\fR and
+\fIminor\fR are integers. The major version number increases in
+any command that includes changes that are not backward compatible
+(i.e. whenever existing applications and scripts may have to change to
+work with the new release). The minor version number increases with
+each new release of a command, except that it resets to zero whenever the
+major version number changes. The array is indexed by the individual
+command name.
+.SH ADDING BLT TO YOUR APPLICATIONS
+It's easy to add BLT to an existing Tk application. BLT requires no
+patches or edits to the Tcl or Tk libraries. To add BLT, simply add the
+following code snippet to your application's tkAppInit.c file.
+.CS
+if (Blt_Init(interp) != TCL_OK) {
+ return TCL_ERROR;
+}
+.CE
+Recompile and link with the BLT library (libBLT.a) and that's it.
+.PP
+Alternately, you can dynamically load BLT, simply by invoking the
+command
+.CS
+package require BLT
+.CE
+from your Tcl script.
+.SH BUGS
+Send bug reports, requests, suggestions, etc. to
+gah at siliconmetrics.com or ghowlett at grandecom.net
+.SH KEYWORDS
+BLT
diff --git a/tlt3.0/doc/barchart.n b/tlt3.0/doc/barchart.n
new file mode 100644
index 0000000..ec2b5f4
--- /dev/null
+++ b/tlt3.0/doc/barchart.n
@@ -0,0 +1,2236 @@
+'\"
+'\" Copyright 1991-1998 by Bell Labs Innovations for Lucent Technologies.
+'\"
+'\" 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 the
+'\" copyright notice and warranty disclaimer appear in supporting documentation,
+'\" and that the names of Lucent Technologies any of their entities not be used
+'\" in advertising or publicity pertaining to distribution of the software
+'\" without specific, written prior permission.
+'\"
+'\" Lucent Technologies disclaims all warranties with regard to this software,
+'\" including all implied warranties of merchantability and fitness. In no event
+'\" shall Lucent Technologies 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
+'\" tortuous action, arising out of or in connection with the use or performance
+'\" of this software.
+'\"
+'\" Barchart widget created by Sani Nassif and George Howlett.
+'\"
+.so man.macros
+.TH barchart n BLT_VERSION BLT "BLT Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+barchart \- Bar chart for plotting X-Y coordinate data.
+.SH SYNOPSIS
+\fBbarchart\fI \fIpathName \fR?\fIoption value\fR?...
+.BE
+.SH DESCRIPTION
+The \fBbarchart\fR command creates a bar chart for plotting
+two-dimensional data (X-Y coordinates). A bar chart is a graphic means
+of comparing numbers by displaying bars of lengths proportional to the
+y-coordinates of the points they represented. The bar chart has many
+configurable components: coordinate axes, elements, legend, grid
+lines, cross hairs, etc. They allow you to customize the look and
+feel of the graph.
+.SH INTRODUCTION
+The \fBbarchart\fR command creates a new window for plotting
+two-dimensional data (X-Y coordinates), using bars of
+various lengths to represent the data points. The bars are drawn in a
+rectangular area displayed in the center of the new window. This is the
+\fIplotting area\fR. The coordinate axes are drawn in
+the margins surrounding the plotting area. By default, the legend is
+drawn in the right margin. The title is displayed in top margin.
+.PP
+A \fBbarchart\fR widget has several configurable components:
+coordinate axes, data elements, legend, grid, cross hairs, pens,
+postscript, and annotation markers. Each component can be queried or
+modified.
+.TP 1i
+\f(CWaxis\fR
+
+Up to four coordinate axes (two X\-coordinate and two Y\-coordinate
+axes) can be displayed, but you can create and use any number of
+axes. Axes control what region of data is displayed and how the data
+is scaled. Each axis consists of the axis line, title, major and minor
+ticks, and tick labels. Tick labels display the value at each major
+tick.
+.TP 1i
+\f(CWcrosshairs\fR
+Cross hairs are used to position the mouse pointer relative to the X
+and Y coordinate axes. Two perpendicular lines, intersecting at the
+current location of the mouse, extend across the plotting area to the
+coordinate axes.
+.TP 1i
+\f(CWelement\fR
+An element represents a set of data to be plotted. It contains an x
+and y vector of values representing the data points. Each
+data point is displayed as a bar where the length of the bar is
+proportional to the ordinate (Y-coordinate) of the data point.
+The appearance of the bar, such as its color, stipple, or relief
+is configurable.
+.sp
+A special case exists when two or more data points have the same
+abscissa (X-coordinate). By default, the bars are overlayed, one on
+top of the other. The bars are drawn in the order of the element
+display list. But you can also configure the bars to be displayed in
+two other ways. They may be displayed as a stack, where each bar
+(with the same abscissa) is stacked on the previous. Or they can be
+drawn side-by-side as thin bars. The width of each bar is a function
+of the number of data points with the same abscissa.
+.TP 1i
+\f(CWgrid\fR
+Extends the major and minor ticks of the X\-axis and/or Y\-axis across the
+plotting area.
+.TP 1i
+\f(CWlegend\fR
+The legend displays the name and symbol of each data element.
+The legend can be drawn in any margin or in the plotting area.
+.TP 1i
+\f(CWmarker\fR
+Markers are used annotate or highlight areas of the graph. For
+example, you could use a text marker to label a particular data
+point. Markers come in various forms: text strings, bitmaps, connected
+line segments, images, polygons, or embedded widgets.
+.TP 1i
+\f(CWpen\fR
+Pens define attributes for elements. Data elements use pens to
+specify how they should be drawn. A data element may use many pens at
+once. Here the particular pen used for a data point is determined
+from each element's weight vector (see the element's \fB\-weight\fR
+and \fB\-style\fR options).
+.TP 1i
+\f(CWpostscript\fR
+The widget can generate encapsulated PostScript output. This component
+has several options to configure how the PostScript is generated.
+.SH SYNTAX
+.DS
+\fBbarchart \fIpathName \fR?\fIoption value\fR?...
+.DE
+The \fBbarchart\fR command creates a new window \fIpathName\fR and makes
+it into a \fBbarchart\fR widget. At the time this command is invoked, there
+must not exist a window named \fIpathName\fR, but \fIpathName\fR's
+parent must exist. Additional options may be specified on the
+command line or in the option database to configure aspects of the
+graph such as its colors and font. See the \fBconfigure\fR operation
+below for the exact details about what \fIoption\fR and \fIvalue\fR
+pairs are valid.
+.PP
+If successful, \fBbarchart\fR returns the path name of the widget. It
+also creates a new Tcl command by the same name. You can use this
+command to invoke various operations that query or modify the graph.
+The general form is:
+.DS
+\fIpathName \fIoperation\fR \fR?\fIarg\fR?...
+.DE
+Both \fIoperation\fR and its arguments determine the exact behavior of
+the command. The operations available for the graph are described in
+the
+.SB "BARCHART OPERATIONS"
+section.
+.PP
+The command can also be used to access components of the graph.
+.DS
+\fIpathName component operation\fR ?\fIarg\fR?...
+.DE
+The operation, now located after the name of the component, is the
+function to be performed on that component. Each component has its own
+set of operations that manipulate that component. They will be
+described below in their own sections.
+.SH EXAMPLE
+The \fBbarchart\fR command creates a new bar chart.
+.CS
+# Create a new bar chart. Plotting area is black.
+barchart .b -plotbackground black
+.CE
+A new Tcl command \f(CW.b\fR is created. This command can be used
+to query and modify the bar chart. For
+example, to change the title of the graph to "My Plot", you use the
+new command and the \fBconfigure\fR operation.
+.CS
+# Change the title.
+\&.b configure -title "My Plot"
+.CE
+To add data elements, you use the command and the \fBelement\fR component.
+.CS
+# Create a new element named "e1"
+\&.b element create e1 \\
+ -xdata { 1 2 3 4 5 6 7 8 9 10 } \\
+ -ydata { 26.18 50.46 72.85 93.31 111.86 128.47 143.14
+ 155.85 166.60 175.38 }
+.CE
+The element's X-Y coordinates are specified using lists of
+numbers. Alternately, BLT vectors could be used to hold the X-Y
+coordinates.
+.CS
+# Create two vectors and add them to the barchart.
+vector xVector yVector
+xVector set { 1 2 3 4 5 6 7 8 9 10 }
+yVector set { 26.18 50.46 72.85 93.31 111.86 128.47 143.14 155.85
+ 166.60 175.38 }
+\&n.b element create e1 -xdata xVector -ydata yVector
+.CE
+The advantage of using vectors is that when you modify one, the graph
+is automatically redrawn to reflect the new values.
+.CS
+# Change the y coordinate of the first point.
+set yVector(0) 25.18
+.CE
+An element named \f(CWe1\fR is now created in \f(CW.b\fR. It
+is automatically added to the display list of elements. You can
+use this list to control in what order elements are displayed.
+To query or reset the element display list, you use the element's
+\fBshow\fR operation.
+.CS
+# Get the current display list
+set elemList [.b element show]
+# Remove the first element so it won't be displayed.
+\&.b element show [lrange $elemList 0 end]
+.CE
+The element will be displayed by as many bars as there are data points
+(in this case there are ten). The bars will be drawn centered at the
+x-coordinate of the data point. All the bars will have the same
+attributes (colors, stipple, etc). The width of each bar is by
+default one unit. You can change this with using the \fB\-barwidth\fR
+option.
+.CS
+# Change the scale of the x-coordinate data
+xVector set { 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 }
+# Make sure we change the bar width too.
+\&.b configure -barwidth 0.2
+.CE
+The height of each bar is proportional to the ordinate (Y-coordinate)
+of the data point.
+.PP
+If two or more data points have the same abscissa (X-coordinate
+value), the bars representing those data points may be drawn in
+various ways.
+The default is to overlay the bars, one on top of the other.
+The ordering is determined from the of element display list. If
+the stacked mode is selected (using the \fB\-barmode\fR configuration
+option), the bars are stacked, each bar above the previous.
+.CS
+# Display the elements as stacked.
+\&.b configure -barmode stacked
+.CE
+If the aligned mode is selected, the bars having the same
+x-coordinates are displayed side by side. The width of each bar is a
+fraction of its normal width, based upon the number of bars with the
+same x-coordinate.
+.CS
+# Display the elements side-by-side.
+\&.b configure -barmode aligned
+.CE
+By default, the element's label in the legend will be also
+\f(CWe1\fR. You can change the label, or specify no legend entry,
+again using the element's \fBconfigure\fR operation.
+.CS
+# Don't display "e1" in the legend.
+\&.b element configure e1 -label ""
+.CE
+You can configure more than just the element's label. An element has
+many attributes such as stipple, foreground and background colors,
+relief, etc.
+.CS
+\&.b element configure e1 -fg red -bg pink \\
+ -stipple gray50
+.CE
+Four coordinate axes are automatically created: \f(CWx\fR, \f(CWx2\fR,
+\f(CWy\fR, and \f(CWy2\fR. And by default, elements are mapped onto the
+axes \f(CWx\fR and \f(CWy\fR. This can be changed with the \fB\-mapx\fR
+and \fB\-mapy\fR options.
+.CS
+# Map "e1" on the alternate y axis "y2".
+\&.b element configure e1 -mapy y2
+.CE
+Axes can be configured in many ways too. For example, you change the
+scale of the Y\-axis from linear to log using the \fBaxis\fR component.
+.CS
+# Y-axis is log scale.
+\&.b axis configure y -logscale yes
+.CE
+One important way axes are used is to zoom in on a particular data
+region. Zooming is done by simply specifying new axis limits using
+the \fB\-min\fR and \fB\-max\fR configuration options.
+.CS
+\&.b axis configure x \-min 1.0 \-max 1.5
+\&.b axis configure y \-min 12.0 \-max 55.15
+.CE
+To zoom interactively, you link the\fBaxis configure\fR operations with
+some user interaction (such as pressing the mouse button), using the
+\fBbind\fR command. To convert between screen and graph coordinates,
+use the \fBinvtransform\fR operation.
+.CS
+# Click the button to set a new minimum
+bind .b <ButtonPress-1> {
+ %W axis configure x \-min [%W axis invtransform x %x]
+ %W axis configure x \-min [%W axis invtransform x %y]
+}
+.CE
+By default, the limits of the axis are determined from data values.
+To reset back to the default limits, set the \fB\-min\fR and
+\fB\-max\fR options to the empty value.
+.CS
+# Reset the axes to autoscale again.
+\&.b axis configure x \-min {} \-max {}
+\&.b axis configure y \-min {} \-max {}
+.CE
+By default, the legend is drawn in the right margin. You can
+change this or any legend configuration options using the
+\fBlegend\fR component.
+.CS
+# Configure the legend font, color, and relief
+\&.b legend configure -position left -relief raised \\
+ -font fixed -fg blue
+.CE
+To prevent the legend from being displayed, turn on the \fB\-hide\fR
+option.
+.CS
+# Don't display the legend.
+\&.b legend configure \-hide yes\fR
+.CE
+The \fBbarchart\fR has simple drawing procedures called markers. They can be
+used to highlight or annotate data in the graph. The types of markers
+available are bitmaps, polygons, lines, or windows. Markers can be
+used, for example, to mark or brush points. For example there may be
+a line marker which indicates some low-water value. Markers are created
+using the \fBmarker\fR operation.
+.CS
+# Create a line represent the low water mark at 10.0
+\&.b marker create line -name "low_water" \\
+ -coords { -Inf 10.0 Inf 10.0 } \\
+ -dashes { 2 4 2 } -fg red -bg blue
+.CE
+This creates a line marker named \f(CWlow_water\fR. It will display a
+horizontal line stretching across the plotting area at the
+y-coordinate 10.0. The coordinates "-Inf" and "Inf" indicate the
+relative minimum and maximum of the axis (in this case the x-axis). By
+default, markers are drawn last, on top of the bars. You can change this
+with the \fB\-under\fR option.
+.CS
+# Draw the marker before elements are drawn.
+\&.b marker configure low_water -under yes
+.CE
+You can add cross hairs or grid lines using the \fBcrosshairs\fR and
+\fBgrid\fR components.
+.CS
+# Display both cross hairs and grid lines.
+\&.b crosshairs configure -hide no -color red
+\&.b grid configure -hide no -dashes { 2 2 }
+.CE
+Finally, to get hardcopy of the graph, use the \fBpostscript\fR
+component.
+.CS
+# Print the bar chart into file "file.ps"
+\&.b postscript output file.ps -maxpect yes -decorations no
+.CE
+This generates a file \f(CWfile.ps\fR containing the encapsulated
+PostScript of the graph. The option \fB\-maxpect\fR says to scale the
+plot to the size of the page. Turning off the \fB\-decorations\fR
+option denotes that no borders or color backgrounds should be
+drawn (i.e. the background of the margins, legend, and plotting
+area will be white).
+.SH SYNTAX
+.DS
+\fBbarchart \fIpathName \fR?\fIoption value\fR?...
+.DE
+The \fBbarchart\fR command creates a new window \fIpathName\fR and makes
+it into a barchart widget. At the time this command is invoked, there
+must not exist a window named \fIpathName\fR, but \fIpathName\fR's
+parent must exist. Additional options may may be specified on the
+command line or in the option database to configure aspects of the
+bar chart such as its colors and font. See the \fBconfigure\fR operation
+below for the exact details as to what \fIoption\fR and \fIvalue\fR
+pairs are valid.
+.PP
+If successful, \fBbarchart\fR returns \fIpathName\fR. It also creates a
+new Tcl command \fIpathName\fR. This command may be used to invoke
+various operations to query or modify the bar chart. It has the general
+form:
+.DS
+\fIpathName \fIoperation\fR \fR?\fIarg\fR?...
+.DE
+Both \fIoperation\fR and its arguments determine the exact behavior of
+the command. The operations available for the bar chart are described in
+the following section.
+.SH "BARCHART OPERATIONS"
+.TP
+\fIpathName \fBbar \fIelemName \fR?\fIoption value\fR?...
+Creates a new barchart element \fIelemName\fR. It's an
+error if an element \fIelemName\fR already exists.
+See the manual for \fBbarchart\fR for details about
+what \fIoption\fR and \fIvalue\fR pairs are valid.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below for the \fBconfigure\fR operation.
+.TP
+\fIpathName \fBconfigure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options of the graph. If
+\fIoption\fR isn't specified, a list describing the current
+options for \fIpathName\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the option \fIoption\fR is set to \fIvalue\fR.
+The following options are valid.
+.RS
+.TP
+\fB\-background \fIcolor\fR
+Sets the background color. This includes the margins and
+legend, but not the plotting area.
+.TP
+\fB\-barmode \fImode\fR
+Indicates how related bar elements will be drawn. Related elements
+have data points with the same abscissas (X-coordinates). \fIMode\fR
+indicates how those segments should be drawn. \fIMode\fR can be
+\f(CWinfront\fR, \f(CWaligned\fR, \f(CWoverlap\fR, or \f(CWstacked\fR.
+The default mode is \f(CWinfront\fR.
+.RS
+.TP 1i
+\f(CWinfront\fR
+Each successive segment is drawn in front of the previous.
+.TP 1i
+\f(CWstacked\fR
+Each successive segment is stacked vertically on top of the previous.
+.TP 1i
+\f(CWaligned\fR
+Segments is displayed aligned from right-to-left.
+.TP 1i
+\f(CWoverlap\fR
+Like \f(CWaligned\fR but segments slightly overlap each other.
+.RE
+.TP
+\fB\-barwidth \fIvalue\fR
+Specifies the width of the bars. This value can be overrided by the
+individual elements using their \fB\-barwidth\fR configuration option.
+\fIValue\fR is the width in terms of graph-coordinates. The
+default width is \f(CW1.0\fR.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the width of the 3\-D border around the outside edge of the widget. The
+\fB\-relief\fR option determines if the border is to be drawn. The
+default is \f(CW2\fR.
+.TP
+\fB\-bottommargin \fIpixels\fR
+Specifies the size of the margin below the X\-coordinate axis. If
+\fIpixels\fR is \f(CW0\fR, the size of the margin is selected automatically.
+The default is \f(CW0\fR.
+.TP
+\fB\-bufferelements \fIboolean\fR
+Indicates whether an internal pixmap to buffer the display of data
+elements should be used. If \fIboolean\fR is true, data elements are
+drawn to an internal pixmap. This option is especially useful when
+the graph is redrawn frequently while the remains data unchanged (for
+example, moving a marker across the plot). See the
+.SB "SPEED TIPS"
+section.
+The default is \f(CW1\fR.
+.TP
+\fB\-cursor \fIcursor\fR
+Specifies the widget's cursor. The default cursor is \f(CWcrosshair\fR.
+.TP
+\fB\-font \fIfontName\fR
+Specifies the font of the graph title. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-18-180-*\fR.
+.TP
+\fB\-halo \fIpixels\fR
+Specifies a maximum distance to consider when searching for the
+closest data point (see the element's \fBclosest\fR operation below).
+Data points further than \fIpixels\fR away are ignored. The default is
+\f(CW0.5i\fR.
+.TP
+\fB\-height \fIpixels\fR
+Specifies the requested height of widget. The default is
+\f(CW4i\fR.
+.TP
+\fB\-invertxy \fIboolean\fR
+Indicates whether the placement X\-axis and Y\-axis should be inverted. If
+\fIboolean\fR is true, the X and Y axes are swapped. The default is
+\f(CW0\fR.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the title should be justified. This matters only when
+the title contains more than one line of text. \fIJustify\fR must be
+\f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-leftmargin \fIpixels\fR
+Sets the size of the margin from the left edge of the window to
+the Y\-coordinate axis. If \fIpixels\fR is \f(CW0\fR, the size is
+calculated automatically. The default is \f(CW0\fR.
+.TP
+\fB\-plotbackground \fIcolor\fR
+Specifies the background color of the plotting area. The default is
+\f(CWwhite\fR.
+.TP
+\fB\-plotborderwidth \fIpixels\fR
+Sets the width of the 3-D border around the plotting area. The
+\fB\-plotrelief\fR option determines if a border is drawn. The
+default is \f(CW2\fR.
+.TP
+\fB\-plotpadx \fIpad\fR
+Sets the amount of padding to be added to the left and right sides of
+the plotting area. \fIPad\fR can be a list of one or two screen
+distances. If \fIpad\fR has two elements, the left side of the
+plotting area entry is padded by the first distance and the right side
+by the second. If \fIpad\fR is just one distance, both the left and
+right sides are padded evenly. The default is \f(CW8\fR.
+.TP
+\fB\-plotpady \fIpad\fR
+Sets the amount of padding to be added to the top and bottom of the
+plotting area. \fIPad\fR can be a list of one or two screen
+distances. If \fIpad\fR has two elements, the top of the plotting
+area is padded by the first distance and the bottom by the second. If
+\fIpad\fR is just one distance, both the top and bottom are padded
+evenly. The default is \f(CW8\fR.
+.TP
+\fB\-plotrelief \fIrelief\fR
+Specifies the 3-D effect for the plotting area. \fIRelief\fR
+specifies how the interior of the plotting area should appear relative
+to rest of the graph; for example, \f(CWraised\fR means the plot should
+appear to protrude from the graph, relative to the surface of the
+graph. The default is \f(CWsunken\fR.
+.TP
+\fB\-relief \fIrelief\fR
+Specifies the 3-D effect for the barchart widget. \fIRelief\fR
+specifies how the graph should appear relative to widget it is packed
+into; for example, \f(CWraised\fR means the graph should
+appear to protrude. The default is \f(CWflat\fR.
+.TP
+\fB\-rightmargin \fIpixels\fR
+Sets the size of margin from the plotting area to the right edge of
+the window. By default, the legend is drawn in this margin. If
+\fIpixels\fR is than 1, the margin size is selected automatically.
+.TP
+\fB\-takefocus\fR \fIfocus\fR
+Provides information used when moving the focus from window to window
+via keyboard traversal (e.g., Tab and Shift-Tab). If \fIfocus\fR is
+\f(CW0\fR, this means that this window should be skipped entirely during
+keyboard traversal. \f(CW1\fR means that the this window should always
+receive the input focus. An empty value means that the traversal
+scripts make the decision whether to focus on the window.
+The default is \f(CW""\fR.
+.TP
+\fB\-tile \fIimage\fR
+Specifies a tiled background for the widget. If \fIimage\fR isn't
+\f(CW""\fR, the background is tiled using \fIimage\fR.
+Otherwise, the normal background color is drawn (see the
+\fB\-background\fR option). \fIImage\fR must be an image created
+using the Tk \fBimage\fR command. The default is \f(CW""\fR.
+.TP
+\fB\-title \fItext\fR
+Sets the title to \fItext\fR. If \fItext\fR is \f(CW""\fR,
+no title will be displayed.
+.TP
+\fB\-topmargin \fIpixels\fR
+Specifies the size of the margin above the x2 axis. If \fIpixels\fR
+is \f(CW0\fR, the margin size is calculated automatically.
+.TP
+\fB\-width \fIpixels\fR
+Specifies the requested width of the widget. The default is
+\f(CW5i\fR.
+.RE
+.TP
+\fIpathName \fBcrosshairs \fIoperation \fR?\fIarg\fR?
+See the
+.SB "CROSSHAIRS COMPONENT"
+section.
+.TP
+\fIpathName \fBelement \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "ELEMENT COMPONENTS"
+section.
+.TP
+\fIpathName \fBextents \fIitem\fR
+Returns the size of a particular item in the graph. \fIItem\fR must
+be either \f(CWleftmargin\fR, \f(CWrightmargin\fR, \f(CWtopmargin\fR,
+\f(CWbottommargin\fR, \f(CWplotwidth\fR, or \f(CWplotheight\fR.
+.TP
+\fIpathName \fBgrid \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "GRID COMPONENT"
+section.
+.TP
+\fIpathName \fBinvtransform \fIwinX winY\fR
+Performs an inverse coordinate transformation, mapping window
+coordinates back to graph-coordinates, using the standard X\-axis and Y\-axis.
+Returns a list of containing the X-Y graph-coordinates.
+.TP
+\fIpathName \fBinside \fIx y\fR
+Returns \f(CW1\fR is the designated screen-coordinate (\fIx\fR and \fIy\fR)
+is inside the plotting area and \f(CW0\fR otherwise.
+.TP
+\fIpathName \fBlegend \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "LEGEND COMPONENT"
+section.
+.TP
+\fIpathName \fBline\fB operation arg\fR...
+The operation is the same as \fBelement\fR.
+.TP
+\fIpathName \fBmarker \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "MARKER COMPONENTS"
+section.
+.TP
+\fIpathName\fR \fBmetafile\fR ?\fIfileName\fR?
+\fIThis operation is for Window platforms only\fR.
+Creates a Windows enhanced metafile of the barchart.
+If present, \fIfileName\fR is the file name of the new metafile.
+Otherwise, the metafile is automatically added to the clipboard.
+.TP
+\fIpathName \fBpostscript \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "POSTSCRIPT COMPONENT"
+section.
+.TP
+\fIpathName \fBsnap \fIphotoName\fR
+Takes a snapshot of the graph and stores the contents in the photo
+image \fIphotoName\fR. \fIPhotoName\fR is the name of a Tk photo
+image that must already exist.
+.TP
+\fIpathName \fBtransform \fIx y\fR
+Performs a coordinate transformation, mapping graph-coordinates to
+window coordinates, using the standard X\-axis and Y\-axis.
+Returns a list containing the X\-Y screen-coordinates.
+.TP
+\fIpathName \fBxaxis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fBx2axis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fByaxis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fBy2axis \fIoperation\fR ?\fIarg\fR?...
+See the
+.SB "AXIS COMPONENTS"
+section.
+.SH "BARCHART COMPONENTS"
+A graph is composed of several components: coordinate axes, data
+elements, legend, grid, cross hairs, postscript, and annotation
+markers. Instead of one big set of configuration options and
+operations, the graph is partitioned, where each component has its own
+configuration options and operations that specifically control that
+aspect or part of the graph.
+.SS "AXIS COMPONENTS"
+Four coordinate axes are automatically created: two X\-coordinate axes
+(\f(CWx\fR and \f(CWx2\fR) and two Y\-coordinate axes (\f(CWy\fR, and
+\f(CWy2\fR). By default, the axis \f(CWx\fR is located in the bottom
+margin, \f(CWy\fR in the left margin, \f(CWx2\fR in the top margin, and
+\f(CWy2\fR in the right margin.
+.PP
+An axis consists of the axis line, title, major and minor ticks, and
+tick labels. Major ticks are drawn at uniform intervals along the
+axis. Each tick is labeled with its coordinate value. Minor ticks
+are drawn at uniform intervals within major ticks.
+.PP
+The range of the axis controls what region of data is plotted.
+Data points outside the minimum and maximum limits of the axis are
+not plotted. By default, the minimum and maximum limits are
+determined from the data, but you can reset either limit.
+.PP
+You can create and use several axes. To create an axis, invoke
+the axis component and its create operation.
+.CS
+# Create a new axis called "temperature"
+\&.b axis create temperature
+.CE
+You map data elements to an axis using the element's \-mapy and \-mapx
+configuration options. They specify the coordinate axes an element
+is mapped onto.
+.CS
+# Now map the temperature data to this axis.
+\&.b element create "temp" \-xdata $x \-ydata $tempData \\
+ \-mapy temperature
+.CE
+While you can have many axes, only four axes can be displayed
+simultaneously. They are drawn in each of the margins surrounding
+the plotting area. The axes \f(CWx\fR and \f(CWy\fR are drawn in the
+bottom and left margins. The axes \f(CWx2\fR and \f(CWy2\fR are drawn in
+top and right margins. Only \f(CWx\fR and \f(CWy\fR are shown by
+default. Note that the axes can have different scales.
+.PP
+To display a different axis, you invoke one of the following
+components: \fBxaxis\fR, \fByaxis\fR, \fBx2axis\fR, and \fBy2axis\fR.
+The \fBuse\fR operation designates the axis to be drawn in the
+corresponding margin: \fBxaxis\fR in the bottom, \fByaxis\fR in the left,
+\fBx2axis\fR in the top, and \fBy2axis\fR in the right.
+.CS
+# Display the axis temperature in the left margin.
+\&.b yaxis use temperature
+.CE
+.PP
+You can configure axes in many ways. The axis scale can be linear or
+logarithmic. The values along the axis can either monotonically
+increase or decrease. If you need custom tick labels, you can specify
+a Tcl procedure to format the label any way you wish. You can
+control how ticks are drawn, by changing the major tick interval
+or the number of minor ticks. You can define non-uniform tick intervals,
+such as for time-series plots.
+.PP
+.TP
+\fIpathName \fBaxis \fBcget \fIaxisName \fIoption\fR
+Returns the current value of the option given by \fIoption\fR for
+\fIaxisName\fR. \fIOption\fR may be any option described below
+for the axis \fBconfigure\fR operation.
+.TP
+\fIpathName \fBaxis \fBconfigure \fIaxisName \fR?\fIaxisName\fR?... ?\fIoption value\fR?...
+Queries or modifies the configuration options of \fIaxisName\fR.
+Several axes can be changed. If \fIoption\fR isn't specified, a list
+describing all the current options for \fIaxisName\fR is returned. If
+\fIoption\fR is specified, but not \fIvalue\fR, then a list describing
+\fIoption\fR is returned. If one or more \fIoption\fR and \fIvalue\fR
+pairs are specified, then for each pair, the axis option \fIoption\fR
+is set to \fIvalue\fR. The following options are valid for axes.
+.RS
+.TP
+\fB\-autorange \fIrange\fR
+Sets the range of values for the axis to \fIrange\fR. The axis limits
+are automatically reset to display the most recent data points in this range.
+If \fIrange\fR is 0.0, the range is
+determined from the limits of the data. If \fB\-min\fR or \fB-max\fR
+are specified, they override this option. The default is \f(CW0.0\fR.
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the axis and tick labels.
+The default is \f(CWblack\fR.
+.TP
+\fB\-command \fIprefix\fR
+Specifies a Tcl command to be invoked when formatting the axis tick
+labels. \fIPrefix\fR is a string containing the name of a Tcl proc and
+any extra arguments for the procedure. This command is invoked for each
+major tick on the axis. Two additional arguments are passed to the
+procedure: the pathname of the widget and the current the numeric
+value of the tick. The procedure returns the formatted tick label. If
+\f(CW""\fR is returned, no label will appear next to the tick. You can
+get the standard tick labels again by setting \fIprefix\fR to
+\f(CW""\fR. The default is \f(CW""\fR.
+.sp 1
+Please note that this procedure is invoked while the bar chart is redrawn.
+You may query the widget's configuration options. But do not reset
+options, because this can have unexpected results.
+.TP
+\fB\-descending \fIboolean\fR
+Indicates whether the values along the axis are monotonically increasing or
+decreasing. If \fIboolean\fR is true, the axis values will be
+decreasing. The default is \f(CW0\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the axis is displayed.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the axis title should be justified. This matters only
+when the axis title contains more than one line of text. \fIJustify\fR
+must be \f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-limits \fIformatStr\fR
+Specifies a printf-like description to format the minimum and maximum
+limits of the axis. The limits are displayed at the top/bottom or
+left/right sides of the plotting area. \fIFormatStr\fR is a list of
+one or two format descriptions. If one description is supplied, both
+the minimum and maximum limits are formatted in the same way. If two,
+the first designates the format for the minimum limit, the second for
+the maximum. If \f(CW""\fR is given as either description, then
+the that limit will not be displayed. The default is \f(CW""\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the axis and tick lines. The default is \f(CW1\fR
+pixel.
+.TP
+\fB\-logscale \fIboolean\fR
+Indicates whether the scale of the axis is logarithmic or linear. If
+\fIboolean\fR is true, the axis is logarithmic. The default scale is
+linear.
+.TP
+\fB\-loose \fIboolean\fR
+Indicates whether the limits of the axis should fit the data points tightly,
+at the outermost data points, or loosely, at the outer tick intervals.
+This is relevant only when the axis limit is automatically calculated.
+If \fIboolean\fR is true, the axis range is "loose".
+The default is \f(CW0\fR.
+.TP
+\fB\-majorticks \fImajorList\fR
+Specifies where to display major axis ticks. You can use this option
+to display ticks at non-uniform intervals. \fIMajorList\fR is a list
+of axis coordinates designating the location of major ticks. No
+minor ticks are drawn. If \fImajorList\fR is \f(CW""\fR,
+major ticks will be automatically computed. The default is \f(CW""\fR.
+.TP
+\fB\-max \fIvalue\fR
+Sets the maximum limit of \fIaxisName\fR. Any data point greater
+than \fIvalue\fR is not displayed. If \fIvalue\fR is \f(CW""\fR,
+the maximum limit is calculated using the largest data value.
+The default is \f(CW""\fR.
+.TP
+\fB\-min \fIvalue\fR
+Sets the minimum limit of \fIaxisName\fR. Any data point less than
+\fIvalue\fR is not displayed. If \fIvalue\fR is \f(CW""\fR,
+the minimum limit is calculated using the smallest data value.
+The default is \f(CW""\fR.
+.TP
+\fB\-minorticks \fIminorList\fR
+Specifies where to display minor axis ticks. You can use this option
+to display minor ticks at non-uniform intervals. \fIMinorList\fR is a
+list of real values, ranging from 0.0 to 1.0, designating the placement of
+a minor tick. No minor ticks are drawn if the \fB\-majortick\fR
+option is also set. If \fIminorList\fR is \f(CW""\fR, minor ticks will
+be automatically computed. The default is \f(CW""\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Specifies the how many degrees to rotate the axis tick labels.
+\fITheta\fR is a real value representing the number of degrees
+to rotate the tick labels. The default is \f(CW0.0\fR degrees.
+.TP
+\fB\-shiftby \fIvalue\fR
+Specifies how much to automatically shift the range of the axis.
+When the new data exceeds the current axis maximum, the maximum
+is increased in increments of \fIvalue\fR. You can use this
+option to prevent the axis limits from being recomputed
+at each new time point. If \fIvalue\fR is 0.0, then no automatic
+shifting is down. The default is \f(CW0.0\fR.
+.TP
+\fB\-showticks \fIboolean\fR
+Indicates whether axis ticks should be drawn. If \fIboolean\fR is
+true, ticks are drawn. If false, only the
+axis line is drawn. The default is \f(CW1\fR.
+.TP
+\fB\-stepsize \fIvalue\fR
+Specifies the interval between major axis ticks. If \fIvalue\fR isn't
+a valid interval (must be less than the axis range),
+the request is ignored and the step size is automatically calculated.
+.TP
+\fB\-subdivisions \fInumber\fR
+Indicates how many minor axis ticks are
+to be drawn. For example, if \fInumber\fR is two, only one minor
+tick is drawn. If \fInumber\fR is one, no minor ticks are
+displayed. The default is \f(CW2\fR.
+.TP
+\fB\-tickfont \fIfontName\fR
+Specifies the font for axis tick labels. The default is
+\f(CW*-Courier-Bold-R-Normal-*-100-*\fR.
+.TP
+\fB\-ticklength \fIpixels\fR
+Sets the length of major and minor ticks (minor ticks are half the
+length of major ticks). If \fIpixels\fR is less than zero, the axis
+will be inverted with ticks drawn pointing towards the plot. The
+default is \f(CW0.1i\fR.
+.TP
+\fB\-title \fItext\fR
+Sets the title of the axis. If \fItext\fR is
+\f(CW""\fR, no axis title will be displayed.
+.TP
+\fB\-titlecolor \fIcolor\fR
+Sets the color of the axis title. The default is \f(CWblack\fR.
+.TP
+\fB\-titlefont \fIfontName\fR
+Specifies the font for axis title. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-14-140-*\fR.
+.PP
+Axis configuration options may be also be set by the \fBoption\fR
+command. The resource class is \f(CWAxis\fR. The resource names
+are the names of the axes (such as \f(CWx\fR or \f(CWx2\fR).
+.CS
+option add *Barchart.Axis.Color blue
+option add *Barchart.x.LogScale true
+option add *Barchart.x2.LogScale false
+.CE
+.RE
+.TP
+\fIpathName \fBaxis \fBcreate \fIaxisName \fR?\fIoption value\fR?...
+Creates a new axis by the name \fIaxisName\fR. No axis by the same
+name can already exist. \fIOption\fR and \fIvalue\fR are described
+in above in the axis \fBconfigure\fR operation.
+.TP
+\fIpathName \fBaxis \fBdelete \fR?\fIaxisName\fR?...
+Deletes the named axes. An axis is not really
+deleted until it is not longer in use, so it's safe to delete
+axes mapped to elements.
+.TP
+\fIpathName \fBaxis invtransform \fIaxisName value\fR
+Performs the inverse transformation, changing the screen-coordinate
+\fIvalue\fR to a graph-coordinate, mapping the value mapped to
+\fIaxisName\fR. Returns the graph-coordinate.
+.TP
+\fIpathName \fBaxis limits \fIaxisName\fR
+Returns a list of the minimum and maximum limits for \fIaxisName\fR. The order
+of the list is \f(CWmin max\fR.
+.TP
+\fIpathName \fBaxis names \fR?\fIpattern\fR?...
+Returns a list of axes matching zero or more patterns. If no
+\fIpattern\fR argument is give, the names of all axes are returned.
+.TP
+\fIpathName \fBaxis transform \fIaxisName value\fR
+Transforms the coordinate \fIvalue\fR to a screen-coordinate by mapping
+the it to \fIaxisName\fR. Returns the transformed screen-coordinate.
+.PP
+Only four axes can be displayed simultaneously. By default, they are
+\f(CWx\fR, \f(CWy\fR, \f(CWx2\fR, and \f(CWy2\fR. You can swap in a different
+axis with \fBuse\fR operation of the special axis components:
+\fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, and \fBy2axis\fR.
+.CS
+\&.g create axis temp
+\&.g create axis time
+\&...
+\&.g xaxis use temp
+\&.g yaxis use time
+.CE
+Only the axes specified for use are displayed on the screen.
+.PP
+The \fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, and \fBy2axis\fR
+components operate on an axis location rather than a specific axis
+like the more general \fBaxis\fR component does. The \fBxaxis\fR
+component manages the X-axis located in the bottom margin (whatever
+axis that happens to be). Likewise, \fByaxis\fR uses the Y-axis in
+the left margin, \fBx2axis\fR the top X-axis, and \fBy2axis\fR the
+right Y-axis.
+.PP
+They implicitly control the axis that is currently using to that
+location. By default, \fBxaxis\fR uses the \f(CWx\fR axis, \fByaxis\fR
+uses \f(CWy\fR, \fBx2axis\fR uses \f(CWx2\fR, and \fBy2axis\fR uses
+\f(CWy2\fR. These components can be more convenient to use than always
+determining what axes are current being displayed by the graph.
+.PP
+The following operations are available for axes. They mirror exactly
+the operations of the \fBaxis\fR component. The \fIaxis\fR argument
+must be \fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, or \fBy2axis\fR.
+.TP
+\fIpathName \fIaxis \fBcget \fIoption\fR
+.TP
+\fIpathName \fIaxis \fBconfigure \fR?\fIoption value\fR?...
+.TP
+\fIpathName \fIaxis\fB invtransform \fIvalue\fR
+.TP
+\fIpathName \fIaxis \fBlimits\fR
+.TP
+\fIpathName \fIaxis\fB transform \fIvalue\fR
+.TP
+\fIpathName \fIaxis\fB use \fR?\fIaxisName\fR?
+Designates the axis \fIaxisName\fR is to be displayed at this
+location. \fIAxisName\fR can not be already in use at another location.
+This command returns the name of the axis currently using this location.
+.SS "CROSSHAIRS COMPONENT"
+Cross hairs consist of two intersecting lines (one vertical and one horizontal)
+drawn completely across the plotting area. They are used to position
+the mouse in relation to the coordinate axes. Cross hairs differ from line
+markers in that they are implemented using XOR drawing primitives.
+This means that they can be quickly drawn and erased without redrawing
+the entire widget.
+.PP
+The following operations are available for cross hairs:
+.TP
+\fIpathName \fBcrosshairs cget \fIoption\fR
+Returns the current value of the cross hairs configuration option
+given by \fIoption\fR. \fIOption\fR may be any option
+described below for the cross hairs \fBconfigure\fR operation.
+.TP
+\fIpathName \fBcrosshairs configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options of the cross hairs. If
+\fIoption\fR isn't specified, a list describing all the current
+options for the cross hairs is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the cross hairs option \fIoption\fR is set to
+\fIvalue\fR.
+The following options are available for cross hairs.
+.RS
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the cross hairs. The default is \f(CWblack\fR.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the cross hairs. \fIDashList\fR is a list of up
+to 11 numbers that alternately represent the lengths of the dashes
+and gaps on the cross hair lines. Each number must be between 1 and
+255. If \fIdashList\fR is \f(CW""\fR, the cross hairs will be solid
+lines.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether cross hairs are drawn. If \fIboolean\fR is true,
+cross hairs are not drawn. The default is \f(CWyes\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Set the width of the cross hair lines. The default is \f(CW1\fR.
+.TP
+\fB\-position \fIpos\fR
+Specifies the screen position where the cross hairs intersect.
+\fIPos\fR must be in the form "\fI at x,y\fR", where \fIx\fR and \fIy\fR
+are the window coordinates of the intersection.
+.PP
+Cross hairs configuration options may be also be set by the
+\fBoption\fR command. The resource name and class are
+\f(CWcrosshairs\fR and \f(CWCrosshairs\fR respectively.
+.CS
+option add *Barchart.Crosshairs.LineWidth 2
+option add *Barchart.Crosshairs.Color red
+.CE
+.RE
+.TP
+\fIpathName \fBcrosshairs off\fR
+Turns off the cross hairs.
+.TP
+\fIpathName \fBcrosshairs on\fR
+Turns on the display of the cross hairs.
+.TP
+\fIpathName \fBcrosshairs toggle\fR
+Toggles the current state of the cross hairs, alternately mapping and
+unmapping the cross hairs.
+.SH "ELEMENTS"
+A data element represents a set of data. It contains x and y vectors
+which are the coordinates of the data points. Elements are displayed
+as bars where the length of the bar is proportional to the ordinate of
+the data point. Elements also control the appearance of the data,
+such as the color, stipple, relief, etc.
+.PP
+When new data elements are created, they are automatically added to a
+list of displayed elements. The display list controls what elements
+are drawn and in what order.
+.PP
+The following operations are available for elements.
+.TP
+\fIpathName \fBelement activate \fIelemName \fR?\fIindex\fR?...
+Specifies the data points of element \fIelemName\fR to be drawn
+using active foreground and background colors. \fIElemName\fR is the
+name of the element and \fIindex\fR is a number representing the index
+of the data point. If no indices are present then all data points
+become active.
+.TP
+\fIpathName \fBelement bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for an element with this
+tag, \fIcommand\fR will be invoked. The syntax is similar to the
+\fBbind\fR command except that it operates on graph elements, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBelement cget \fIelemName \fIoption\fR
+Returns the current value of the element configuration option given by
+\fIoption\fR. \fIOption\fR may be any of the options described below
+for the element \fBconfigure\fR operation.
+.TP
+\fIpathName \fBelement closest \fIx y\fR ?\fIoption value\fR?... ?\fIelemName\fR?...
+Finds the data point representing the bar closest to the window
+coordinates \fIx\fR and \fIy\fR in the element \fIelemName\fR.
+\fIElemName\fR is the name of an element, which must be currently displayed.
+If no elements are specified, then all displayed elements are searched. It
+returns a key-value list containing the name of the closest element,
+the index of its closest point, and the graph-coordinates of the
+point. If no data point within the threshold distance can be found,
+\f(CW""\fR is returned. The following \fIoption\fR-\fIvalue\fR pairs
+are available.
+.RS
+.TP
+\fB\-halo \fIpixels\fR
+Specifies a threshold distance where selected data points are ignored.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+If this option isn't specified, then it defaults to the value of the
+\fBbarchart\fR's \fB\-halo\fR option.
+.RE
+.TP
+\fIpathName \fBelement configure \fIelemName \fR?\fIelemName\fR... ?\fIoption value\fR?...
+Queries or modifies the configuration options for elements. Several
+elements can be modified at the same time. If \fIoption\fR isn't
+specified, a list describing all the current options for
+\fIelemName\fR is returned. If \fIoption\fR is specified, but not
+\fIvalue\fR, then a list describing the option \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the element option \fIoption\fR is set
+to \fIvalue\fR. The following options are valid for elements.
+.RS
+.TP
+\fB\-activepen \fIpenName\fR
+Specifies pen to use to draw active element. If \fIpenName\fR is
+\f(CW""\fR, no active elements will be drawn. The default is
+\f(CWactiveLine\fR.
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for the element. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events for elements. Each tag in the list matching the current event
+sequence will have its Tcl command executed. Implicitly the name of
+the element is always the first tag in the list. The default value is
+\f(CWall\fR.
+.TP
+\fB\-background \fIcolor\fR
+Sets the the color of the border around each bar. The default is
+\f(CWwhite\fR.
+.TP
+\fB\-barwidth \fIvalue\fR
+Specifies the width the bars drawn for the element. \fIValue\fR is
+the width in X-coordinates. If this option isn't
+specified, the width of each bar is the value of the widget's
+\fB\-barwidth\fR option.
+.TP
+\fB\-baseline \fIvalue\fR
+Specifies the baseline of the bar segments. This affects how bars are
+drawn since bars are drawn from their respective y-coordinate the
+baseline. By default the baseline is \f(CW0.0\fR.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the border width of the 3-D border drawn around the outside of
+each bar. The \fB\-relief\fR option determines if such a border is
+drawn. \fIPixels\fR must be a valid screen distance like \f(CW2\fR or
+\f(CW0.25i\fR. The default is \f(CW2\fR.
+.TP
+\fB\-data \fIcoordList\fR
+Specifies the X\-Y coordinates of the data. \fICoordList\fR is a
+list of numeric expressions representing the X\-Y coordinate pairs
+of each data point.
+.TP
+\fB\-foreground \fIcolor\fR
+Sets the color of the interior of the bars.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the element is displayed. The default is \f(CWno\fR.
+.TP
+\fB\-label \fItext\fR
+Sets the element's label in the legend. If \fItext\fR
+is \f(CW""\fR, the element will have no entry in the legend.
+The default label is the element's name.
+.TP
+\fB\-mapx \fIxAxis\fR
+Selects the X\-axis to map the element's X\-coordinates onto.
+\fIXAxis\fR must be the name of an axis. The default is \f(CWx\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Selects the Y\-axis to map the element's Y\-coordinates onto.
+\fIYAxis\fR must be the name of an axis. The default is \f(CWy\fR.
+.TP
+\fB\-relief \fIstring\fR
+Specifies the 3-D effect desired for bars. \fIRelief\fR indicates how
+the interior of the bar should appear relative to the surface of the
+chart; for example, \f(CWraised\fR means the bar should appear to
+protrude from the surface of the plotting area. The default is
+\f(CWraised\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies a stipple pattern with which to draw the bars. If
+\fIbitmap\fR is \f(CW""\fR, then the bar is drawn in a solid fashion.
+.TP
+\fB\-xdata \fIxVector\fR
+Specifies the x-coordinate vector of the data.
+\fIXVector\fR is the name of a BLT vector or a
+list of numeric expressions.
+.TP
+\fB\-ydata \fIyVector\fR
+Specifies the y-coordinate vector of the data.
+\fIYVector\fR is the name of a BLT vector or a list of
+numeric expressions.
+.PP
+Element configuration options may also be set by the
+\fBoption\fR command. The resource names in the option database
+are prefixed by \f(CWelem\fR.
+.CS
+option add *Barchart.Element.background blue
+.CE
+.RE
+.TP
+\fIpathName \fBelement create \fIelemName\fR ?\fIoption value\fR?...
+Creates a new element \fIelemName\fR. Element
+names must be unique, so an element \fIelemName\fR may not already
+exist. If additional arguments are present, they specify any of the
+element options valid for element \fBconfigure\fR operation.
+.TP
+\fIpathName \fBelement deactivate \fIpattern\fR...
+Deactivates all the elements matching \fIpattern\fR for the graph.
+Elements whose names match any of the patterns given are redrawn
+using their normal colors.
+.TP
+\fIpathName \fBelement delete\fR ?\fIpattern\fR?...
+Deletes all the elements matching \fIpattern\fR for the graph.
+Elements whose names match any of the patterns given are deleted.
+The graph will be redrawn without the deleted elements.
+.TP
+\fIpathName \fBelement exists \fIelemName\fR
+Returns \f(CW1\fR if an element \fIelemName\fR currently exists and
+\f(CW0\fR otherwise.
+.TP
+\fIpathName \fBelement names \fR?\fIpattern\fR?...
+Returns the elements matching one or more pattern. If no
+\fIpattern\fR is given, the names of all elements is returned.
+.TP
+\fIpathName \fBelement show\fR ?\fInameList\fR?
+Queries or modifies the element display list. The element display
+list designates the elements drawn and in what
+order. \fINameList\fR is a list of elements to be displayed in the
+order they are named. If there is no \fInameList\fR argument,
+the current display list is returned.
+.TP
+\fIpathName \fBelement type\fR \fIelemName\fR
+Returns the type of \fIelemName\fR.
+If the element is a bar element, the commands returns the string
+\f(CW"bar"\fR, otherwise it returns \f(CW"line"\fR.
+.CE
+.SS "GRID COMPONENT"
+Grid lines extend from the major and minor ticks of each axis
+horizontally or vertically across the plotting area. The following
+operations are available for grid lines.
+.TP
+\fIpathName \fBgrid cget \fIoption\fR
+Returns the current value of the grid line configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described below
+for the grid \fBconfigure\fR operation.
+.TP
+\fIpathName \fBgrid configure\fR ?\fIoption value\fR?...
+Queries or modifies the configuration options for grid lines. If
+\fIoption\fR isn't specified, a list describing all the current
+grid options for \fIpathName\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the grid line option \fIoption\fR is set to
+\fIvalue\fR. The following options are valid for grid lines.
+.RS
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the grid lines. The default is \f(CWblack\fR.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the grid lines. \fIDashList\fR is a list of up
+to 11 numbers that alternately represent the lengths of the dashes
+and gaps on the grid lines. Each number must be between 1 and 255.
+If \fIdashList\fR is \f(CW""\fR, the grid will be solid lines.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the grid should be drawn. If \fIboolean\fR
+is true, grid lines are not shown. The default is \f(CWyes\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of grid lines. The default width is \f(CW1\fR.
+.TP
+\fB\-mapx \fIxAxis\fR
+Specifies the X\-axis to display grid lines. \fIXAxis\fR
+must be the name of an axis or \f(CW""\fR for no grid lines.
+The default is \f(CW""\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Specifies the Y\-axis to display grid lines. \fIYAxis\fR
+must be the name of an axis or \f(CW""\fR for no grid lines.
+The default is \f(CWy\fR.
+.TP
+\fB\-minor \fIboolean\fR
+Indicates whether the grid lines should be drawn for minor ticks.
+If \fIboolean\fR is true, the lines will appear at
+minor tick intervals. The default is \f(CW1\fR.
+.PP
+Grid configuration options may also be set by the
+\fBoption\fR command. The resource name and class are \f(CWgrid\fR and
+\f(CWGrid\fR respectively.
+.CS
+option add *Barchart.grid.LineWidth 2
+option add *Barchart.Grid.Color black
+.CE
+.RE
+.TP
+\fIpathName \fBgrid off\fR
+Turns off the display the grid lines.
+.TP
+\fIpathName \fBgrid on\fR
+Turns on the display the grid lines.
+.TP
+\fIpathName \fBgrid toggle\fR
+Toggles the display of the grid.
+.SS "LEGEND COMPONENT"
+The legend displays a list of the data elements. Each entry consists
+of the element's symbol and label. The legend can appear in any
+margin (the default location is in the right margin). It
+can also be positioned anywhere within the plotting area.
+.PP
+The following operations are valid for the legend.
+.TP
+\fIpathName \fBlegend activate \fIpattern\fR...
+Selects legend entries to be drawn using the active legend colors and relief.
+All entries whose element names match \fIpattern\fR are selected. To
+be selected, the element name must match only one \fIpattern\fR.
+.TP
+\fIpathName \fBlegend bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for a legend entry with this
+tag, \fIcommand\fR will be invoked. Implicitly the element names
+in the entry are tags. The syntax is similar to the
+\fBbind\fR command except that it operates on legend entries, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBlegend cget \fIoption\fR
+Returns the current value of a legend configuration option.
+\fIOption\fR may be any option described below in the
+legend \fBconfigure\fR operation.
+.TP
+\fIpathName \fBlegend configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options for the legend. If
+\fIoption\fR isn't specified, a list describing the current
+legend options for \fIpathName\fR is returned. If \fIoption\fR is
+specified, but not \fIvalue\fR, then a list describing \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the legend option \fIoption\fR is set
+to \fIvalue\fR. The following options are valid for the legend.
+.RS
+.TP
+\fB\-activebackground \fIcolor\fR
+Sets the background color for active legend entries. All legend
+entries marked active (see the legend \fBactivate\fR operation) are
+drawn using this background color.
+.TP
+\fB\-activeborderwidth \fIpixels\fR
+Sets the width of the 3-D border around the outside edge of the active legend
+entries. The default is \f(CW2\fR.
+.TP
+\fB\-activeforeground \fIcolor\fR
+Sets the foreground color for active legend entries. All legend
+entries marked as active (see the legend \fBactivate\fR operation) are
+drawn using this foreground color.
+.TP
+\fB\-activerelief \fIrelief\fR
+Specifies the 3-D effect desired for active legend entries.
+\fIRelief\fR denotes how the interior of the entry should appear
+relative to the legend; for example, \f(CWraised\fR means the entry
+should appear to protrude from the legend, relative to the surface of
+the legend. The default is \f(CWflat\fR.
+.TP
+\fB\-anchor \fIanchor\fR
+Tells how to position the legend relative to the positioning point for
+the legend. This is dependent on the value of the \fB\-position\fR
+option. The default is \f(CWcenter\fR.
+.RS
+.TP 1.25i
+\f(CWleft\fR or \f(CWright\fR
+The anchor describes how to position the legend vertically.
+.TP
+\f(CWtop\fR or \f(CWbottom\fR
+The anchor describes how to position the legend horizontally.
+.TP
+\f(CW at x,y\fR
+The anchor specifies how to position the legend relative to the
+positioning point. For example, if \fIanchor\fR is \f(CWcenter\fR then
+the legend is centered on the point; if \fIanchor\fR is \f(CWn\fR then
+the legend will be drawn such that the top center point of the
+rectangular region occupied by the legend will be at the positioning
+point.
+.TP
+\f(CWplotarea\fR
+The anchor specifies how to position the legend relative to the
+plotting area. For example, if \fIanchor\fR is \f(CWcenter\fR then the
+legend is centered in the plotting area; if \fIanchor\fR is \f(CWne\fR
+then the legend will be drawn such that occupies the upper right
+corner of the plotting area.
+.RE
+.TP
+\fB\-background \fIcolor\fR
+Sets the background color of the legend. If \fIcolor\fR is \f(CW""\fR,
+the legend background with be transparent.
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for legend entries. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events for legend entries. Each tag in the list matching the current
+event sequence will have its Tcl command executed. The default value
+is \f(CWall\fR.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the width of the 3-D border around the outside edge of the legend (if
+such border is being drawn; the \fBrelief\fR option determines this).
+The default is \f(CW2\fR pixels.
+.TP
+\fB\-font \fIfontName\fR
+\fIFontName\fR specifies a font to use when drawing the labels of each
+element into the legend. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-12-120-*\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Sets the foreground color of the text drawn for the element's label.
+The default is \f(CWblack\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the legend should be displayed. If \fIboolean\fR is
+true, the legend will not be draw. The default is \f(CWno\fR.
+.TP
+\fB\-ipadx \fIpad\fR
+Sets the amount of internal padding to be added to the width of each
+legend entry. \fIPad\fR can be a list of one or two screen distances. If
+\fIpad\fR has two elements, the left side of the legend entry is
+padded by the first distance and the right side by the second. If
+\fIpad\fR is just one distance, both the left and right sides are padded
+evenly. The default is \f(CW2\fR.
+.TP
+\fB\-ipady \fIpad\fR
+Sets an amount of internal padding to be added to the height of each
+legend entry. \fIPad\fR can be a list of one or two screen distances. If
+\fIpad\fR has two elements, the top of the entry is padded by the
+first distance and the bottom by the second. If \fIpad\fR is just
+one distance, both the top and bottom of the entry are padded evenly.
+The default is \f(CW2\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the padding to the left and right exteriors of the legend.
+\fIPad\fR can be a list of one or two screen distances. If \fIpad\fR
+has two elements, the left side of the legend is padded by the first
+distance and the right side by the second. If \fIpad\fR has just one
+distance, both the left and right sides are padded evenly. The
+default is \f(CW4\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the padding above and below the legend. \fIPad\fR can be a list
+of one or two screen distances. If \fIpad\fR has two elements, the area above
+the legend is padded by the first distance and the area below by the
+second. If \fIpad\fR is just one distance, both the top and
+bottom areas are padded evenly. The default is \f(CW0\fR.
+.TP
+\fB\-position \fIpos\fR
+Specifies where the legend is drawn. The
+\fB\-anchor\fR option also affects where the legend is positioned. If
+\fIpos\fR is \f(CWleft\fR, \f(CWleft\fR, \f(CWtop\fR, or \f(CWbottom\fR, the
+legend is drawn in the specified margin. If \fIpos\fR is
+\f(CWplotarea\fR, then the legend is drawn inside the plotting area at a
+particular anchor. If \fIpos\fR is in the form "\fI at x,y\fR", where
+\fIx\fR and \fIy\fR are the window coordinates, the legend is drawn in
+the plotting area at the specified coordinates. The default is
+\f(CWright\fR.
+.TP
+\fB\-raised \fIboolean\fR
+Indicates whether the legend is above or below the data elements. This
+matters only if the legend is in the plotting area. If \fIboolean\fR
+is true, the legend will be drawn on top of any elements that may
+overlap it. The default is \f(CWno\fR.
+.TP
+\fB\-relief \fIrelief\fR
+Specifies the 3-D effect for the border around the legend.
+\fIRelief\fR specifies how the interior of the legend should appear
+relative to the bar chart; for example, \f(CWraised\fR means the legend
+should appear to protrude from the bar chart, relative to the surface of
+the bar chart. The default is \f(CWsunken\fR.
+.PP
+Legend configuration options may also be set by the \fBoption\fR
+command. The resource name and class are \f(CWlegend\fR and
+\f(CWLegend\fR respectively.
+.CS
+option add *Barchart.legend.Foreground blue
+option add *Barchart.Legend.Relief raised
+.CE
+.RE
+.TP
+\fIpathName \fBlegend deactivate \fIpattern\fR...
+Selects legend entries to be drawn using the normal legend colors and
+relief. All entries whose element names match \fIpattern\fR are
+selected. To be selected, the element name must match only one
+\fIpattern\fR.
+.TP
+\fIpathName \fBlegend get \fIpos\fR
+Returns the name of the element whose entry is at the screen position
+\fIpos\fR in the legend. \fIPos\fR must be in the form "\fI at x,y\fR",
+where \fIx\fR and \fIy\fR are window coordinates. If the given
+coordinates do not lie over a legend entry, \f(CW""\fR is returned.
+.SS "PEN COMPONENTS"
+Pens define attributes for elements.
+Pens mirror the configuration options of data elements that pertain to
+how symbols and lines are drawn. Data elements use pens to determine
+how they are drawn. A data element may use several pens at once. In
+this case, the pen used for a particular data point is determined from
+each element's weight vector (see the element's \fB\-weight\fR and
+\fB\-style\fR options).
+.PP
+One pen, called \f(CWactiveBar\fR, is automatically created.
+It's used as the default active pen for elements. So you can change
+the active attributes for all elements by simply reconfiguring this
+pen.
+.CS
+\&.g pen configure "activeBar" -fg green -bg green4
+.CE
+You can create and use several pens. To create a pen, invoke
+the pen component and its create operation.
+.CS
+\&.g pen create myPen
+.CE
+You map pens to a data element using either the element's
+\fB\-pen\fR or \fB\-activepen\fR options.
+.CS
+\&.g element create "e1" -xdata $x -ydata $tempData \\
+ -pen myPen
+.CE
+An element can use several pens at once. This is done by specifying
+the name of the pen in the element's style list (see the
+\fB\-styles\fR option).
+.CS
+\&.g element configure "e1" -styles { myPen 2.0 3.0 }
+.CE
+This says that any data point with a weight between 2.0 and 3.0
+is to be drawn using the pen \f(CWmyPen\fR. All other points
+are drawn with the element's default attributes.
+.PP
+The following operations are available for pen components.
+.PP
+.TP
+\fIpathName \fBpen \fBcget \fIpenName \fIoption\fR
+Returns the current value of the option given by \fIoption\fR for
+\fIpenName\fR. \fIOption\fR may be any option described below
+for the pen \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpen \fBconfigure \fIpenName \fR?\fIpenName\fR... ?\fIoption value\fR?...
+Queries or modifies the configuration options of
+\fIpenName\fR. Several pens can be modified at once. If \fIoption\fR
+isn't specified, a list describing the current options for
+\fIpenName\fR is returned. If \fIoption\fR is specified, but not
+\fIvalue\fR, then a list describing \fIoption\fR is returned. If one
+or more \fIoption\fR and \fIvalue\fR pairs are specified, then for
+each pair, the pen option \fIoption\fR is set to \fIvalue\fR. The
+following options are valid for pens.
+.RS
+.TP
+\fB\-background \fIcolor\fR
+Sets the the color of the border around each bar. The default is
+\f(CWwhite\fR.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the border width of the 3-D border drawn around the outside of
+each bar. The \fB\-relief\fR option determines if such a border is
+drawn. \fIPixels\fR must be a valid screen distance like \f(CW2\fR or
+\f(CW0.25i\fR. The default is \f(CW2\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Sets the color of the interior of the bars.
+.TP
+\fB\-relief \fIstring\fR
+Specifies the 3-D effect desired for bars. \fIRelief\fR indicates how
+the interior of the bar should appear relative to the surface of the
+chart; for example, \f(CWraised\fR means the bar should appear to
+protrude from the bar chart, relative to the surface of the plotting
+area. The default is \f(CWraised\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies a stipple pattern with which to draw the bars. If
+\fIbitmap\fR is \f(CW""\fR, then the bar is drawn in a solid fashion.
+.TP
+\fB\-type \fIelemType\fR
+Specifies the type of element the pen is to be used with.
+This option should only be employed when creating the pen. This
+is for those that wish to mix different types of elements (bars and
+lines) on the same graph. The default type is "bar".
+.PP
+Pen configuration options may be also be set by the \fBoption\fR
+command. The resource class is \f(CWPen\fR. The resource names
+are the names of the pens.
+.CS
+option add *Barchart.Pen.Foreground blue
+option add *Barchart.activeBar.foreground green
+.CE
+.RE
+.TP
+\fIpathName \fBpen \fBcreate \fIpenName \fR?\fIoption value\fR?...
+Creates a new pen by the name \fIpenName\fR. No pen by the same
+name can already exist. \fIOption\fR and \fIvalue\fR are described
+in above in the pen \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpen \fBdelete \fR?\fIpenName\fR?...
+Deletes the named pens. A pen is not really
+deleted until it is not longer in use, so it's safe to delete
+pens mapped to elements.
+.TP
+\fIpathName \fBpen names \fR?\fIpattern\fR?...
+Returns a list of pens matching zero or more patterns. If no
+\fIpattern\fR argument is give, the names of all pens are returned.
+.SS "POSTSCRIPT COMPONENT"
+The barchart can generate encapsulated PostScript output. There
+are several configuration options you can specify to control how the
+plot will be generated. You can change the page dimensions and
+borders. The plot itself can be scaled, centered, or rotated to
+landscape. The PostScript output can be written directly to a file or
+returned through the interpreter.
+.PP
+The following postscript operations are available.
+.TP
+\fIpathName \fBpostscript cget \fIoption\fR
+Returns the current value of the postscript option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below for the postscript \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpostscript configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options for PostScript
+generation. If \fIoption\fR isn't specified, a list describing
+the current postscript options for \fIpathName\fR is returned. If
+\fIoption\fR is specified, but not \fIvalue\fR, then a list describing
+\fIoption\fR is returned. If one or more \fIoption\fR and \fIvalue\fR
+pairs are specified, then for each pair, the postscript option
+\fIoption\fR is set to \fIvalue\fR. The following postscript options
+are available.
+.RS
+.TP
+\fB\-center \fIboolean\fR
+Indicates whether the plot should be centered on the PostScript page. If
+\fIboolean\fR is false, the plot will be placed in the upper left
+corner of the page. The default is \f(CW1\fR.
+.TP
+\fB\-colormap \fIvarName\fR
+\fIVarName\fR must be the name of a global array variable that
+specifies a color mapping from the X color name to PostScript. Each
+element of \fIvarName\fR must consist of PostScript code to set a
+particular color value (e.g. ``\f(CW1.0 1.0 0.0 setrgbcolor\fR''). When
+generating color information in PostScript, the array variable \fIvarName\fR
+is checked if an element of the name as the color exists. If so, it uses
+its value as the PostScript
+command to set the color. If this option hasn't been specified, or if
+there isn't an entry in \fIvarName\fR for a given color, then it uses
+the red, green, and blue intensities from the X color.
+.TP
+\fB\-colormode \fImode\fR
+Specifies how to output color information. \fIMode\fR must be either
+\f(CWcolor\fR (for full color output), \f(CWgray\fR (convert all colors to
+their gray-scale equivalents) or \f(CWmono\fR (convert foreground colors
+to black and background colors to white). The default mode is
+\f(CWcolor\fR.
+.TP
+\fB\-fontmap \fIvarName\fR
+\fIVarName\fR must be the name of a global array variable that
+specifies a font mapping from the X font name to PostScript. Each
+element of \fIvarName\fR must consist of a Tcl list with one or two
+elements; the name and point size of a PostScript font.
+When outputting PostScript commands for a particular font, the array
+variable \fIvarName\fR is checked to see if an element by the
+specified font exists. If there is such an element, then the font
+information contained in that element is used in the PostScript
+output. (If the point size is omitted from the list, the point size
+of the X font is used). Otherwise the X font is examined in an
+attempt to guess what PostScript font to use. This works only for
+fonts whose foundry property is \fIAdobe\fR (such as Times, Helvetica,
+Courier, etc.). If all of this fails then the font defaults to
+\f(CWHelvetica-Bold\fR.
+.TP
+\fB\-decorations \fIboolean\fR
+Indicates whether PostScript commands to generate color backgrounds and 3-D
+borders will be output. If \fIboolean\fR is false, the graph will
+background will be white and no 3-D borders will be generated. The
+default is \f(CW1\fR.
+.TP
+\fB\-height \fIpixels\fR
+Sets the height of the plot. This lets you print the bar chart with a
+height different from the one drawn on the screen. If
+\fIpixels\fR is 0, the height is the same as the widget's height.
+The default is \f(CW0\fR.
+.TP
+\fB\-landscape \fIboolean\fR
+If \fIboolean\fR is true, this specifies the printed area is to be
+rotated 90 degrees. In non-rotated output the X\-axis of the printed
+area runs along the short dimension of the page (``portrait''
+orientation); in rotated output the X\-axis runs along the long
+dimension of the page (``landscape'' orientation). Defaults to
+\f(CW0\fR.
+.TP
+\fB\-maxpect \fIboolean\fR
+Indicates to scale the plot so that it fills the PostScript page.
+The aspect ratio of the barchart is still retained. The default is
+\f(CW0\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the horizontal padding for the left and right page borders. The
+borders are exterior to the plot. \fIPad\fR can be a list of one or
+two screen distances. If \fIpad\fR has two elements, the left border is padded
+by the first distance and the right border by the second. If
+\fIpad\fR has just one distance, both the left and right borders are
+padded evenly. The default is \f(CW1i\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the vertical padding for the top and bottom page borders. The
+borders are exterior to the plot. \fIPad\fR can be a list of one or
+two screen distances. If \fIpad\fR has two elements, the top border is padded
+by the first distance and the bottom border by the second. If
+\fIpad\fR has just one distance, both the top and bottom borders are
+padded evenly. The default is \f(CW1i\fR.
+.TP
+\fB\-paperheight \fIpixels\fR
+Sets the height of the postscript page. This can be used to select
+between different page sizes (letter, A4, etc). The default height is
+\f(CW11.0i\fR.
+.TP
+\fB\-paperwidth \fIpixels\fR
+Sets the width of the postscript page. This can be used to select
+between different page sizes (letter, A4, etc). The default width is
+\f(CW8.5i\fR.
+.TP
+\fB\-width \fIpixels\fR
+Sets the width of the plot. This lets you generate a plot
+of a width different from that of the widget. If \fIpixels\fR
+is 0, the width is the same as the widget's width. The default is
+\f(CW0\fR.
+.PP
+Postscript configuration options may be also be set by the
+\fBoption\fR command. The resource name and class are
+\f(CWpostscript\fR and \f(CWPostscript\fR respectively.
+.CS
+option add *Barchart.postscript.Decorations false
+option add *Barchart.Postscript.Landscape true
+.CE
+.RE
+.TP
+\fIpathName \fBpostscript output \fR?\fIfileName\fR? ?\fIoption value\fR?...
+Outputs a file of encapsulated PostScript. If a
+\fIfileName\fR argument isn't present, the command returns the
+PostScript. If any \fIoption-value\fR pairs are present, they set
+configuration options controlling how the PostScript is generated.
+\fIOption\fR and \fIvalue\fR can be anything accepted by the
+postscript \fBconfigure\fR operation above.
+.SS "MARKER COMPONENTS"
+Markers are simple drawing procedures used to annotate or highlight
+areas of the graph. Markers have various types: text strings,
+bitmaps, images, connected lines, windows, or polygons. They can be
+associated with a particular element, so that when the element is
+hidden or un-hidden, so is the marker. By default, markers are the
+last items drawn, so that data elements will appear in
+behind them. You can change this by configuring the \fB\-under\fR
+option.
+.PP
+Markers, in contrast to elements, don't affect the scaling of the
+coordinate axes. They can also have \fIelastic\fR coordinates
+(specified by \f(CW-Inf\fR and \f(CWInf\fR respectively) that translate
+into the minimum or maximum limit of the axis. For example, you can
+place a marker so it always remains in the lower left corner of the
+plotting area, by using the coordinates \f(CW-Inf\fR,\f(CW-Inf\fR.
+.PP
+The following operations are available for markers.
+.TP
+\fIpathName \fBmarker after \fImarkerId\fR ?\fIafterId\fR?
+Changes the order of the markers, drawing the first
+marker after the second. If no second \fIafterId\fR argument is
+specified, the marker is placed at the end of the display list. This
+command can be used to control how markers are displayed since markers
+are drawn in the order of this display list.
+.TP
+\fIpathName \fBmarker before \fImarkerId\fR ?\fIbeforeId\fR?
+Changes the order of the markers, drawing the first
+marker before the second. If no second \fIbeforeId\fR argument is
+specified, the marker is placed at the beginning of the display list.
+This command can be used to control how markers are displayed since
+markers are drawn in the order of this display list.
+.TP
+\fIpathName \fBmarker bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for a marker with this
+tag, \fIcommand\fR will be invoked. The syntax is similar to the
+\fBbind\fR command except that it operates on graph markers, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBmarker cget \fIoption\fR
+Returns the current value of the marker configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below in the \fBconfigure\fR operation.
+.TP
+\fIpathName \fBmarker configure \fImarkerId\fR ?\fIoption value\fR?...
+Queries or modifies the configuration options for markers. If
+\fIoption\fR isn't specified, a list describing the current
+options for \fImarkerId\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the marker option \fIoption\fR is set to \fIvalue\fR.
+.sp
+The following options are valid for all markers.
+Each type of marker also has its own type-specific options.
+They are described in the sections below.
+.RS
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for the marker. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events for markers are handled. Each tag in the list matching the
+current event sequence will have its Tcl command executed. Implicitly
+the name of the marker is always the first tag in the list.
+The default value is \f(CWall\fR.
+.TP
+\fB\-coords \fIcoordList\fR
+Specifies the coordinates of the marker. \fICoordList\fR is
+a list of graph-coordinates. The number of coordinates required
+is dependent on the type of marker. Text, image, and window markers
+need only two coordinates (an X\-Y coordinate). Bitmap markers
+can take either two or four coordinates (if four, they represent the
+corners of the bitmap). Line markers
+need at least four coordinates, polygons at least six.
+If \fIcoordList\fR is \f(CW""\fR, the marker will not be displayed.
+The default is \f(CW""\fR.
+.TP
+\fB\-element \fIelemName\fR
+Links the marker with the element \fIelemName\fR. The marker is
+drawn only if the element is also currently displayed (see the
+element's \fBshow\fR operation). If \fIelemName\fR is \f(CW""\fR, the
+marker is always drawn. The default is \f(CW""\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the marker is drawn. If \fIboolean\fR is true,
+the marker is not drawn. The default is \f(CWno\fR.
+.TP
+\fB\-mapx \fIxAxis\fR
+Specifies the X\-axis to map the marker's X\-coordinates onto.
+\fIXAxis\fR must the name of an axis. The default is \f(CWx\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Specifies the Y\-axis to map the marker's Y\-coordinates onto.
+\fIYAxis\fR must the name of an axis. The default is \f(CWy\fR.
+.TP
+\fB\-name \fImarkerId\fR
+Changes the identifier for the marker. The identifier \fImarkerId\fR
+can not already be used by another marker. If this option
+isn't specified, the marker's name is uniquely generated.
+.TP
+\fB\-under \fIboolean\fR
+Indicates whether the marker is drawn below/above data
+elements. If \fIboolean\fR is true, the marker is be drawn
+underneath the data elements. Otherwise, the marker is
+drawn on top of the element. The default is \f(CW0\fR.
+.TP
+\fB\-xoffset \fIpixels\fR
+Specifies a screen distance to offset the marker horizontally.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+The default is \f(CW0\fR.
+.TP
+\fB\-yoffset \fIpixels\fR
+Specifies a screen distance to offset the markers vertically.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+The default is \f(CW0\fR.
+.PP
+Marker configuration options may also be set by the \fBoption\fR command.
+The resource class is either \f(CWBitmapMarker\fR, \f(CWImageMarker\fR,
+\f(CWLineMarker\fR, \f(CWPolygonMarker\fR, \f(CWTextMarker\fR, or \f(CWWindowMarker\fR,
+depending on the type of marker. The resource name is the name of the
+marker.
+.CS
+option add *Barchart.TextMarker.Foreground white
+option add *Barchart.BitmapMarker.Foreground white
+option add *Barchart.m1.Background blue
+.CE
+.RE
+.TP
+\fIpathName \fBmarker create \fItype\fR ?\fIoption value\fR?...
+Creates a marker of the selected type. \fIType\fR may be either
+\f(CWtext\fR, \f(CWline\fR, \f(CWbitmap\fR, \f(CWimage\fR, \f(CWpolygon\fR, or
+\f(CWwindow\fR. This command returns the marker identifier,
+used as the \fImarkerId\fR argument in the other marker-related
+commands. If the \fB\-name\fR option is used, this overrides the
+normal marker identifier. If the name provided is already used for
+another marker, the new marker will replace the old.
+.TP
+\fIpathName \fBmarker delete\fR ?\fIname\fR?...
+Removes one of more markers. The graph will automatically be redrawn
+without the marker.\fR.
+.TP
+\fIpathName \fBmarker exists \fImarkerId\fR
+Returns \f(CW1\fR if the marker \fImarkerId\fR exists and \f(CW0\fR
+otherwise.
+.TP
+\fIpathName \fBmarker names\fR ?\fIpattern\fR?
+Returns the names of all the markers that currently exist. If
+\fIpattern\fR is supplied, only those markers whose names match it
+will be returned.
+.TP
+\fIpathName \fBmarker type \fImarkerId\fR
+Returns the type of the marker given by \fImarkerId\fR, such as
+\f(CWline\fR or \f(CWtext\fR. If \fImarkerId\fR is not a valid a marker
+identifier, \f(CW""\fR is returned.
+.SS "BITMAP MARKERS"
+A bitmap marker displays a bitmap. The size of the
+bitmap is controlled by the number of coordinates specified. If two
+coordinates, they specify the position of the top-left corner of the
+bitmap. The bitmap retains its normal width and height. If four
+coordinates, the first and second pairs of coordinates represent the
+corners of the bitmap. The bitmap will be stretched or reduced as
+necessary to fit into the bounding rectangle.
+.PP
+Bitmap markers are created with the marker's \fBcreate\fR operation in
+the form:
+.DS
+\fIpathName \fBmarker create bitmap \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR pairs, each
+sets a configuration options for the marker. These
+same \fIoption\fR\-\fIvalue\fR pairs may be used with the marker's
+\fBconfigure\fR operation.
+.PP
+The following options are specific to bitmap markers:
+.TP
+\fB\-background \fIcolor\fR
+Same as the \fB\-fill\fR option.
+.TP
+\fB\-bitmap \fIbitmap\fR
+Specifies the bitmap to be displayed. If \fIbitmap\fR is \f(CW""\fR,
+the marker will not be displayed. The default is \f(CW""\fR.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the bitmap. If \fIcolor\fR is the empty
+string, no background will be transparent. The default background color is
+\f(CW""\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Same as the \fB\-outline\fR option.
+.TP
+\fB\-mask \fImask\fR
+Specifies a mask for the bitmap to be displayed. This mask is a bitmap
+itself, denoting the pixels that are transparent. If \fImask\fR is
+\f(CW""\fR, all pixels of the bitmap will be drawn. The default is
+\f(CW""\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the foreground color of the bitmap. The default value is \f(CWblack\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Sets the rotation of the bitmap. \fITheta\fR is a real number
+representing the angle of rotation in degrees. The marker is first
+rotated and then placed according to its anchor position. The default
+rotation is \f(CW0.0\fR.
+.SS "IMAGE MARKERS"
+A image marker displays an image. Image markers are
+created with the marker's \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create image \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to image markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the image relative to the
+positioning point for the image. For example, if \fIanchor\fR
+is \f(CWcenter\fR then the image is centered on the point; if
+\fIanchor\fR is \f(CWn\fR then the image will be drawn such that
+the top center point of the rectangular region occupied by the
+image will be at the positioning point.
+This option defaults to \f(CWcenter\fR.
+.TP
+\fB\-image \fIimage\fR
+Specifies the image to be drawn.
+If \fIimage\fR is \f(CW""\fR, the marker will not be
+drawn. The default is \f(CW""\fR.
+.SS "LINE MARKERS"
+A line marker displays one or more connected line segments.
+Line markers are created with marker's \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create line \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to line markers:
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the line. \fIDashList\fR is a list of up to 11
+numbers that alternately represent the lengths of the dashes and gaps
+on the line. Each number must be between 1 and 255. If
+\fIdashList\fR is \f(CW""\fR, the marker line will be solid.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the line. This color is used with
+striped lines (see the \fB\-fdashes\R option). If \fIcolor\fR is
+the empty string, no background color is drawn (the line will be
+dashed, not striped). The default background color is \f(CW""\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the lines.
+The default width is \f(CW0\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the foreground color of the line. The default value is \f(CWblack\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies a stipple pattern used to draw the line, rather than
+a solid line.
+\fIBitmap\fR specifies a bitmap to use as the stipple
+pattern. If \fIbitmap\fR is \f(CW""\fR, then the
+line is drawn in a solid fashion. The default is \f(CW""\fR.
+.SS "POLYGON MARKERS"
+A polygon marker displays a closed region described as two or more
+connected line segments. It is assumed the first and
+last points are connected. Polygon markers are created using the
+marker \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create polygon \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the \fBmarker configure\fR command to change the marker's
+configuration.
+The following options are supported for polygon markers:
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the outline of the polygon. \fIDashList\fR is a
+list of up to 11 numbers that alternately represent the lengths of
+the dashes and gaps on the outline. Each number must be between 1 and
+255. If \fIdashList\fR is \f(CW""\fR, the outline will be a solid line.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the fill color of the polygon. If \fIcolor\fR is \f(CW""\fR, then
+the interior of the polygon is transparent.
+The default is \f(CWwhite\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the outline of the polygon. If \fIpixels\fR is zero,
+no outline is drawn. The default is \f(CW0\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color of the outline of the polygon. If the polygon is
+stippled (see the \fB\-stipple\fR option), then this represents the
+foreground color of the stipple. The default is \f(CWblack\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies that the polygon should be drawn with a stippled pattern
+rather than a solid color. \fIBitmap\fR specifies a bitmap to use as
+the stipple pattern. If \fIbitmap\fR is \f(CW""\fR, then the polygon is
+filled with a solid color (if the \fB\-fill\fR option is set). The
+default is \f(CW""\fR.
+.SS "TEXT MARKERS"
+A text marker displays a string of characters on one or more lines of
+text. Embedded newlines cause line breaks. They may be used to
+annotate regions of the graph. Text markers are created with the
+\fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create text \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR pairs,
+each sets a configuration option for the text marker.
+These same \fIoption\fR\-\fIvalue\fR pairs may be used with the
+marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to text markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the text relative to the
+positioning point for the text. For example, if \fIanchor\fR is
+\f(CWcenter\fR then the text is centered on the point; if
+\fIanchor\fR is \f(CWn\fR then the text will be drawn such that the
+top center point of the rectangular region occupied by the text will
+be at the positioning point. This default is \f(CWcenter\fR.
+.TP
+\fB\-background \fIcolor\fR
+Same as the \fB\-fill\fR option.
+.TP
+\fB\-font \fIfontName\fR
+Specifies the font of the text. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-120-*\fR.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the text. If \fIcolor\fR is the empty
+string, no background will be transparent. The default background color is
+\f(CW""\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Same as the \fB\-outline\fR option.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the text should be justified. This matters only when
+the marker contains more than one line of text. \fIJustify\fR must be
+\f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color of the text. The default value is \f(CWblack\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the padding to the left and right exteriors of the text.
+\fIPad\fR can be a list of one or two screen distances. If \fIpad\fR
+has two elements, the left side of the text is padded by the first
+distance and the right side by the second. If \fIpad\fR has just one
+distance, both the left and right sides are padded evenly. The
+default is \f(CW4\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the padding above and below the text. \fIPad\fR can be a list of
+one or two screen distances. If \fIpad\fR has two elements, the area above the
+text is padded by the first distance and the area below by the second.
+If \fIpad\fR is just one distance, both the top and bottom areas
+are padded evenly. The default is \f(CW4\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Specifies the number of degrees to rotate the text. \fITheta\fR is a
+real number representing the angle of rotation. The marker is first
+rotated along its center and is then drawn according to its anchor
+position. The default is \f(CW0.0\fR.
+.TP
+\fB\-text \fItext\fR
+Specifies the text of the marker. The exact way the text is
+displayed may be affected by other options such as \fB\-anchor\fR or
+\fB\-rotate\fR.
+.SS "WINDOW MARKERS"
+A window marker displays a widget at a given position.
+Window markers are created with the marker's \fBcreate\fR operation in
+the form:
+.DS
+\fIpathName \fBmarker create window \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR command.
+.PP
+The following options are specific to window markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the widget relative to the
+positioning point for the widget. For example, if \fIanchor\fR is
+\f(CWcenter\fR then the widget is centered on the point; if \fIanchor\fR
+is \f(CWn\fR then the widget will be displayed such that the top center
+point of the rectangular region occupied by the widget will be at the
+positioning point. This option defaults to \f(CWcenter\fR.
+.TP
+\fB\-height \fIpixels\fR
+Specifies the height to assign to the marker's window. If this option
+isn't specified, or if it is specified as \f(CW""\fR, then the window is
+given whatever height the widget requests internally.
+.TP
+\fB\-width \fIpixels\fR
+Specifies the width to assign to the marker's window. If this option
+isn't specified, or if it is specified as \f(CW""\fR, then the window is
+given whatever width the widget requests internally.
+.TP
+\fB\-window \fIpathName\fR
+Specifies the widget to be managed by the barchart. \fIPathName\fR must
+be a child of the \fBbarchart\fR widget.
+.SH "GRAPH COMPONENT BINDINGS"
+Specific barchart components, such as elements, markers and legend
+entries, can have a command trigger when event occurs in them, much
+like canvas items in Tk's canvas widget. Not all event sequences are
+valid. The only binding events that may be specified are those
+related to the mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR,
+\fBButtonPress\fR, \fBMotion\fR, and \fBKeyPress\fR).
+.PP
+Only one element or marker can be picked during an event. This means,
+that if the mouse is directly over both an element and a marker, only
+the uppermost component is selected. This isn't true for legend entries.
+Both a legend entry and an element (or marker) binding commands
+will be invoked if both items are picked.
+.PP
+It is possible for multiple bindings to match a particular event.
+This could occur, for example, if one binding is associated with the
+element name and another is associated with one of the element's tags
+(see the \fB\-bindtags\fR option). When this occurs, all of the
+matching bindings are invoked. A binding associated with the element
+name is invoked first, followed by one binding for each of the element's
+bindtags. If there are multiple matching bindings for a single tag,
+then only the most specific binding is invoked. A continue command
+in a binding script terminates that script, and a break command
+terminates that script and skips any remaining scripts for the event,
+just as for the bind command.
+.PP
+The \fB\-bindtags\fR option for these components controls addition
+tag names which can be matched. Implicitly elements and markers
+always have tags matching their names. Setting the value of
+the \fB\-bindtags\fR option doesn't change this.
+.SH "C LANGUAGE API"
+You can manipulate data elements from the C language. There
+may be situations where it is too expensive to translate the data
+values from ASCII strings. Or you might want to read data in a
+special file format.
+.PP
+Data can manipulated from the C language using BLT vectors.
+You specify the X-Y data coordinates of an element as vectors and
+manipulate the vector from C. The barchart will be redrawn automatically
+after the vectors are updated.
+.PP
+From Tcl, create the vectors and configure the element to use them.
+.CS
+vector X Y
+\&.g element configure line1 -xdata X -ydata Y
+.CE
+To set data points from C, you pass the values as arrays of doubles
+using the \fBBlt_ResetVector\fR call. The vector is reset with the
+new data and at the next idle point (when Tk re-enters its event
+loop), the graph will be redrawn automatically.
+.CS
+#include <tcl.h>
+#include <blt.h>
+
+register int i;
+Blt_Vector *xVec, *yVec;
+double x[50], y[50];
+
+/* Get the BLT vectors "X" and "Y" (created above from Tcl) */
+if ((Blt_GetVector(interp, "X", 50, &xVec) != TCL_OK) ||
+ (Blt_GetVector(interp, "Y", 50, &yVec) != TCL_OK)) {
+ return TCL_ERROR;
+}
+
+for (i = 0; i < 50; i++) {
+ x[i] = i * 0.02;
+ y[i] = sin(x[i]);
+}
+
+/* Put the data into BLT vectors */
+if ((Blt_ResetVector(xVec, x, 50, 50, TCL_VOLATILE) != TCL_OK) ||
+ (Blt_ResetVector(yVec, y, 50, 50, TCL_VOLATILE) != TCL_OK)) {
+ return TCL_ERROR;
+}
+.CE
+See the \fBvector\fR manual page for more details.
+.SH SPEED TIPS
+There may be cases where the bar chart needs to be drawn and updated as
+quickly as possible. If drawing speed becomes a big
+problem, here are a few tips to speed up displays.
+.TP 2
+\(bu
+Try to minimize the number of data points. The more data points
+looked at, the more work the bar chart must do.
+.TP 2
+\(bu
+If your data is generated as floating point values, the time required
+to convert the data values to and from ASCII strings can be
+significant, especially when there any many data points. You can
+avoid the redundant string-to-decimal conversions using the C API to
+BLT vectors.
+.TP 2
+\(bu
+Don't stipple or dash the element. Solid bars are much faster.
+.TP 2
+\(bu
+If you update data elements frequently, try turning off the
+widget's \fB\-bufferelements\fR option. When the bar chart is first
+displayed, it draws data elements into an internal pixmap. The pixmap
+acts as a cache, so that when the bar chart needs to be redrawn again, and
+the data elements or coordinate axes haven't changed, the pixmap is
+simply copied to the screen. This is especially useful when you are
+using markers to highlight points and regions on the bar chart. But if
+the bar chart is updated frequently, changing either the element data or
+coordinate axes, the buffering becomes redundant.
+.SH LIMITATIONS
+Auto-scale routines do not use requested min/max limits
+as boundaries when the axis is logarithmically scaled.
+.PP
+The PostScript output generated for polygons with more than 1500
+points may exceed the limits of some printers (See PostScript Language
+Reference Manual, page 568). The work-around is to break the polygon
+into separate pieces.
+.SH KEYWORDS
+bar chart, widget
diff --git a/tlt3.0/doc/graph.n b/tlt3.0/doc/graph.n
new file mode 100644
index 0000000..c631975
--- /dev/null
+++ b/tlt3.0/doc/graph.n
@@ -0,0 +1,2397 @@
+'\"
+'\" Copyright 1991-1998 by Bell Labs Innovations for Lucent Technologies.
+'\"
+'\" 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 the
+'\" copyright notice and warranty disclaimer appear in supporting documentation,
+'\" and that the names of Lucent Technologies any of their entities not be used
+'\" in advertising or publicity pertaining to distribution of the software
+'\" without specific, written prior permission.
+'\"
+'\" Lucent Technologies disclaims all warranties with regard to this software,
+'\" including all implied warranties of merchantability and fitness. In no event
+'\" shall Lucent Technologies 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
+'\" tortuous action, arising out of or in connection with the use or performance
+'\" of this software.
+'\"
+'\" Graph widget created by Sani Nassif and George Howlett.
+'\"
+.so man.macros
+.TH graph n BLT_VERSION BLT "BLT Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+graph \- 2D graph for plotting X\-Y coordinate data.
+.SH SYNOPSIS
+\fBgraph\fI \fIpathName \fR?\fIoption value\fR?...
+.BE
+.SH DESCRIPTION
+The \fBgraph\fR command creates a graph for plotting
+two-dimensional data (X\-Y coordinates). It has many configurable
+components: coordinate axes, elements, legend, grid lines, cross
+hairs, etc. They allow you to customize the look and feel of the
+graph.
+.SH INTRODUCTION
+The \fBgraph\fR command creates a new window for plotting
+two-dimensional data (X\-Y coordinates). Data points are plotted in a
+rectangular area displayed in the center of the new window. This is the
+\fIplotting area\fR. The coordinate axes are drawn in the
+margins around the plotting area. By default, the legend is displayed
+in the right margin. The title is displayed in top margin.
+.PP
+The \fBgraph\fR widget is composed of several components: coordinate
+axes, data elements, legend, grid, cross hairs, pens, postscript, and
+annotation markers.
+.TP 1i
+\f(CWaxis\fR
+The graph has four standard axes (\f(CWx\fR, \f(CWx2\fR,
+\f(CWy\fR, and \f(CWy2\fR), but you can create and display any number
+of axes. Axes control what region of data is
+displayed and how the data is scaled. Each axis consists of the axis
+line, title, major and minor ticks, and tick labels. Tick labels
+display the value at each major tick.
+.TP 1i
+\f(CWcrosshairs\fR
+Cross hairs are used to position the mouse pointer relative to the X
+and Y coordinate axes. Two perpendicular lines, intersecting at the
+current location of the mouse, extend across the plotting area to the
+coordinate axes.
+.TP 1i
+\f(CWelement\fR
+An element represents a set of data points. Elements can be plotted
+with a symbol at each data point and lines connecting the points.
+The appearance of the element, such as its symbol, line width, and
+color is configurable.
+.TP 1i
+\f(CWgrid\fR
+Extends the major and minor ticks of the X\-axis and/or Y\-axis across the
+plotting area.
+.TP 1i
+\f(CWlegend\fR
+The legend displays the name and symbol of each data element.
+The legend can be drawn in any margin or in the plotting area.
+.TP 1i
+\f(CWmarker\fR
+Markers are used annotate or highlight areas of the graph. For
+example, you could use a polygon marker to fill an area under a
+curve, or a text marker to label a particular data point. Markers
+come in various forms: text strings, bitmaps, connected line
+segments, images, polygons, or embedded widgets.
+.TP 1i
+\f(CWpen\fR
+Pens define attributes (both symbol and line style) for elements.
+Data elements use pens to specify how they should be drawn. A data
+element may use many pens at once. Here, the particular pen
+used for a data point is determined from each element's weight
+vector (see the element's \fB\-weight\fR and \fB\-style\fR options).
+.TP 1i
+\f(CWpostscript\fR
+The widget can generate encapsulated PostScript output. This component
+has several options to configure how the PostScript is generated.
+.SH SYNTAX
+.DS
+\fBgraph \fIpathName \fR?\fIoption value\fR?...
+.DE
+The \fBgraph\fR command creates a new window \fIpathName\fR and makes
+it into a \fBgraph\fR widget. At the time this command is invoked, there
+must not exist a window named \fIpathName\fR, but \fIpathName\fR's
+parent must exist. Additional options may be specified on the
+command line or in the option database to configure aspects of the
+graph such as its colors and font. See the \fBconfigure\fR operation
+below for the exact details about what \fIoption\fR and \fIvalue\fR
+pairs are valid.
+.PP
+If successful, \fBgraph\fR returns the path name of the widget. It
+also creates a new Tcl command by the same name. You can use this
+command to invoke various operations that query or modify the graph.
+The general form is:
+.DS
+\fIpathName \fIoperation\fR \fR?\fIarg\fR?...
+.DE
+Both \fIoperation\fR and its arguments determine the exact behavior of
+the command. The operations available for the graph are described in
+the
+.SB "GRAPH OPERATIONS"
+section.
+.PP
+The command can also be used to access components of the graph.
+.DS
+\fIpathName component operation\fR ?\fIarg\fR?...
+.DE
+The operation, now located after the name of the component, is the
+function to be performed on that component. Each component has its own
+set of operations that manipulate that component. They will be
+described below in their own sections.
+.SH EXAMPLE
+The \fBgraph\fR command creates a new graph.
+.CS
+# Create a new graph. Plotting area is black.
+graph .g \-plotbackground black
+.CE
+A new Tcl command \f(CW.g\fR is also created. This command can be used
+to query and modify the graph. For example, to change the title of
+the graph to "My Plot", you use the new command and the graph's
+\fBconfigure\fR operation.
+.CS
+# Change the title.
+\&.g configure \-title "My Plot"
+.CE
+A graph has several components. To access a particular component you
+use the component's name. For example, to add data elements, you use
+the new command and the \fBelement\fR component.
+.CS
+# Create a new element named "line1"
+\&.g element create line1 \\
+ \-xdata { 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 } \\
+ \-ydata { 26.18 50.46 72.85 93.31 111.86 128.47 143.14
+ 155.85 166.60 175.38 }
+.CE
+The element's X-Y coordinates are specified using lists of
+numbers. Alternately, BLT vectors could be used to hold the X\-Y
+coordinates.
+.CS
+# Create two vectors and add them to the graph.
+vector xVec yVec
+xVec set { 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 }
+yVec set { 26.18 50.46 72.85 93.31 111.86 128.47 143.14 155.85
+ 166.60 175.38 }
+\&.g element create line1 \-xdata xVec \-ydata yVec
+.CE
+The advantage of using vectors is that when you modify one, the graph
+is automatically redrawn to reflect the new values.
+.CS
+# Change the y coordinate of the first point.
+set yVector(0) 25.18
+.CE
+An element named \f(CWe1\fR is now created in \f(CW.b\fR. It
+is automatically added to the display list of elements. You can
+use this list to control in what order elements are displayed.
+To query or reset the element display list, you use the element's
+\fBshow\fR operation.
+.CS
+# Get the current display list
+set elemList [.b element show]
+# Remove the first element so it won't be displayed.
+\&.b element show [lrange $elemList 0 end]
+.CE
+The element will be displayed by as many bars as there are data points
+(in this case there are ten). The bars will be drawn centered at the
+x-coordinate of the data point. All the bars will have the same
+attributes (colors, stipple, etc). The width of each bar is by
+default one unit. You can change this with using the \fB\-barwidth\fR
+option.
+.CS
+# Change the X\-Y coordinates of the first point.
+set xVec(0) 0.18
+set yVec(0) 25.18
+.CE
+An element named \f(CWline1\fR is now created in \f(CW.g\fR. By
+default, the element's label in the legend will be also \f(CWline1\fR.
+You can change the label, or specify no legend entry, again using the
+element's \fBconfigure\fR operation.
+.CS
+# Don't display "line1" in the legend.
+\&.g element configure line1 \-label ""
+.CE
+You can configure more than just the element's label. An element has
+many attributes such as symbol type and size, dashed or solid lines,
+colors, line width, etc.
+.CS
+\&.g element configure line1 \-symbol square \-color red \\
+ \-dashes { 2 4 2 } \-linewidth 2 \-pixels 2c
+.CE
+Four coordinate axes are automatically created: \f(CWx\fR, \f(CWx2\fR,
+\f(CWy\fR, and \f(CWy2\fR. And by default, elements are mapped onto the
+axes \f(CWx\fR and \f(CWy\fR. This can be changed with the \fB\-mapx\fR
+and \fB\-mapy\fR options.
+.CS
+# Map "line1" on the alternate Y\-axis "y2".
+\&.g element configure line1 \-mapy y2
+.CE
+Axes can be configured in many ways too. For example, you change the
+scale of the Y\-axis from linear to log using the \fBaxis\fR component.
+.CS
+# Y\-axis is log scale.
+\&.g axis configure y \-logscale yes
+.CE
+One important way axes are used is to zoom in on a particular data
+region. Zooming is done by simply specifying new axis limits using
+the \fB\-min\fR and \fB\-max\fR configuration options.
+.CS
+\&.g axis configure x \-min 1.0 \-max 1.5
+\&.g axis configure y \-min 12.0 \-max 55.15
+.CE
+To zoom interactively, you link the \fBaxis configure\fR operations with
+some user interaction (such as pressing the mouse button), using the
+\fBbind\fR command. To convert between screen and graph coordinates,
+use the \fBinvtransform\fR operation.
+.CS
+# Click the button to set a new minimum
+bind .g <ButtonPress-1> {
+ %W axis configure x \-min [%W axis invtransform x %x]
+ %W axis configure x \-min [%W axis invtransform x %y]
+}
+.CE
+By default, the limits of the axis are determined from data values.
+To reset back to the default limits, set the \fB\-min\fR and
+\fB\-max\fR options to the empty value.
+.CS
+# Reset the axes to autoscale again.
+\&.g axis configure x \-min {} \-max {}
+\&.g axis configure y \-min {} \-max {}
+.CE
+By default, the legend is drawn in the right margin. You can
+change this or any legend configuration options using the
+\fBlegend\fR component.
+.CS
+# Configure the legend font, color, and relief
+\&.g legend configure \-position left \-relief raised \\
+ \-font fixed \-fg blue
+.CE
+To prevent the legend from being displayed, turn on the \fB\-hide\fR
+option.
+.CS
+# Don't display the legend.
+\&.g legend configure \-hide yes\fR
+.CE
+The \fBgraph\fR widget has simple drawing procedures called markers.
+They can be used to highlight or annotate data in the graph. The types
+of markers available are bitmaps, images, polygons, lines, or windows.
+Markers can be used, for example, to mark or brush points. In this
+example, is a text marker that labels the data first point. Markers
+are created using the \fBmarker\fR component.
+.CS
+# Create a label for the first data point of "line1".
+\&.g marker create text \-name first_marker \-coords { 0.2 26.18 } \\
+ \-text "start" \-anchor se \-xoffset -10 \-yoffset -10
+.CE
+This creates a text marker named \f(CWfirst_marker\fR. It will display
+the text "start" near the coordinates of the first data point. The
+\fB\-anchor\fR, \fB\-xoffset\fR, and \fB\-yoffset\fR options are used
+to display the marker above and to the left of the data point, so that
+the data point isn't covered by the marker. By default,
+markers are drawn last, on top of data. You can change this with the
+\fB\-under\fR option.
+.CS
+# Draw the label before elements are drawn.
+\&.g marker configure first_marker \-under yes
+.CE
+You can add cross hairs or grid lines using the \fBcrosshairs\fR and
+\fBgrid\fR components.
+.CS
+# Display both cross hairs and grid lines.
+\&.g crosshairs configure \-hide no \-color red
+\&.g grid configure \-hide no \-dashes { 2 2 }
+# Set up a binding to reposition the crosshairs.
+bind .g <Motion> {
+ .g crosshairs configure -position @%x,%y
+}
+.CE
+The crosshairs are repositioned as the mouse pointer is moved
+in the graph. The pointer X-Y coordinates define the center
+of the crosshairs.
+.PP
+Finally, to get hardcopy of the graph, use the \fBpostscript\fR
+component.
+.CS
+# Print the graph into file "file.ps"
+\&.g postscript output file.ps \-maxpect yes \-decorations no
+.CE
+This generates a file \f(CWfile.ps\fR containing the encapsulated
+PostScript of the graph. The option \fB\-maxpect\fR says to scale the
+plot to the size of the page. Turning off the \fB\-decorations\fR
+option denotes that no borders or color backgrounds should be
+drawn (i.e. the background of the margins, legend, and plotting
+area will be white).
+.SH "GRAPH OPERATIONS"
+.TP
+\fIpathName \fBaxis \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "AXIS COMPONENTS"
+section.
+.TP
+\fIpathName \fBbar \fIelemName \fR?\fIoption value\fR?...
+Creates a new barchart element \fIelemName\fR. It's an
+error if an element \fIelemName\fR already exists.
+See the manual for \fBbarchart\fR for details about
+what \fIoption\fR and \fIvalue\fR pairs are valid.
+.TP
+\fIpathName \fBcget\fR \fIoption\fR
+Returns the current value of the configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below for the \fBconfigure\fR operation.
+.TP
+\fIpathName \fBconfigure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options of the graph. If
+\fIoption\fR isn't specified, a list describing the current
+options for \fIpathName\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the option \fIoption\fR is set to \fIvalue\fR.
+The following options are valid.
+.RS
+.TP
+\fB\-aspect \fIwidth/height\fR
+Force a fixed aspect ratio of \fIwidth/height\fR, a floating point number.
+.TP
+\fB\-background \fIcolor\fR
+Sets the background color. This includes the margins and
+legend, but not the plotting area.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the width of the 3\-D border around the outside edge of the widget. The
+\fB\-relief\fR option determines if the border is to be drawn. The
+default is \f(CW2\fR.
+.TP
+\fB\-bottommargin \fIpixels\fR
+If non-zero, overrides the computed size of the margin extending
+below the X\-coordinate axis.
+If \fIpixels\fR is \f(CW0\fR, the automatically computed size is used.
+The default is \f(CW0\fR.
+.TP
+\fB\-bufferelements \fIboolean\fR
+Indicates whether an internal pixmap to buffer the display of data
+elements should be used. If \fIboolean\fR is true, data elements are
+drawn to an internal pixmap. This option is especially useful when
+the graph is redrawn frequently while the remains data unchanged (for
+example, moving a marker across the plot). See the
+.SB "SPEED TIPS"
+section.
+The default is \f(CW1\fR.
+.TP
+\fB\-cursor \fIcursor\fR
+Specifies the widget's cursor. The default cursor is \f(CWcrosshair\fR.
+.TP
+\fB\-font \fIfontName\fR
+Specifies the font of the graph title. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-18-180-*\fR.
+.TP
+\fB\-halo \fIpixels\fR
+Specifies a maximum distance to consider when searching for the
+closest data point (see the element's \fBclosest\fR operation below).
+Data points further than \fIpixels\fR away are ignored. The default is
+\f(CW0.5i\fR.
+.TP
+\fB\-height \fIpixels\fR
+Specifies the requested height of widget. The default is
+\f(CW4i\fR.
+.TP
+\fB\-invertxy \fIboolean\fR
+Indicates whether the placement X\-axis and Y\-axis should be inverted. If
+\fIboolean\fR is true, the X and Y axes are swapped. The default is
+\f(CW0\fR.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the title should be justified. This matters only when
+the title contains more than one line of text. \fIJustify\fR must be
+\f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-leftmargin \fIpixels\fR
+If non-zero, overrides the computed size of the margin extending
+from the left edge of the window to the Y\-coordinate axis.
+If \fIpixels\fR is \f(CW0\fR, the automatically computed size is used.
+The default is \f(CW0\fR.
+.TP
+\fB\-plotbackground \fIcolor\fR
+Specifies the background color of the plotting area. The default is
+\f(CWwhite\fR.
+.TP
+\fB\-plotborderwidth \fIpixels\fR
+Sets the width of the 3-D border around the plotting area. The
+\fB\-plotrelief\fR option determines if a border is drawn. The
+default is \f(CW2\fR.
+.TP
+\fB\-plotpadx \fIpad\fR
+Sets the amount of padding to be added to the left and right sides of
+the plotting area. \fIPad\fR can be a list of one or two screen
+distances. If \fIpad\fR has two elements, the left side of the
+plotting area entry is padded by the first distance and the right side
+by the second. If \fIpad\fR is just one distance, both the left and
+right sides are padded evenly. The default is \f(CW8\fR.
+.TP
+\fB\-plotpady \fIpad\fR
+Sets the amount of padding to be added to the top and bottom of the
+plotting area. \fIPad\fR can be a list of one or two screen
+distances. If \fIpad\fR has two elements, the top of the plotting
+area is padded by the first distance and the bottom by the second. If
+\fIpad\fR is just one distance, both the top and bottom are padded
+evenly. The default is \f(CW8\fR.
+.TP
+\fB\-plotrelief \fIrelief\fR
+Specifies the 3-D effect for the plotting area. \fIRelief\fR
+specifies how the interior of the plotting area should appear relative
+to rest of the graph; for example, \f(CWraised\fR means the plot should
+appear to protrude from the graph, relative to the surface of the
+graph. The default is \f(CWsunken\fR.
+.TP
+\fB\-relief \fIrelief\fR
+Specifies the 3-D effect for the graph widget. \fIRelief\fR
+specifies how the graph should appear relative to widget it is packed
+into; for example, \f(CWraised\fR means the graph should
+appear to protrude. The default is \f(CWflat\fR.
+.TP
+\fB\-rightmargin \fIpixels\fR
+If non-zero, overrides the computed size of the margin extending
+from the plotting area to the right edge of
+the window. By default, the legend is drawn in this margin.
+If \fIpixels\fR is \f(CW0\fR, the automatically computed size is used.
+The default is \f(CW0\fR.
+.TP
+\fB\-takefocus\fR \fIfocus\fR
+Provides information used when moving the focus from window to window
+via keyboard traversal (e.g., Tab and Shift-Tab). If \fIfocus\fR is
+\f(CW0\fR, this means that this window should be skipped entirely during
+keyboard traversal. \f(CW1\fR means that the this window should always
+receive the input focus. An empty value means that the traversal
+scripts make the decision whether to focus on the window.
+The default is \f(CW""\fR.
+.TP
+\fB\-tile \fIimage\fR
+Specifies a tiled background for the widget. If \fIimage\fR isn't
+\f(CW""\fR, the background is tiled using \fIimage\fR.
+Otherwise, the normal background color is drawn (see the
+\fB\-background\fR option). \fIImage\fR must be an image created
+using the Tk \fBimage\fR command. The default is \f(CW""\fR.
+.TP
+\fB\-title \fItext\fR
+Sets the title to \fItext\fR. If \fItext\fR is \f(CW""\fR,
+no title will be displayed.
+.TP
+\fB\-topmargin \fIpixels\fR
+If non-zero, overrides the computed size of the margin above the x2
+axis. If \fIpixels\fR is \f(CW0\fR, the automatically computed size
+is used. The default is \f(CW0\fR.
+.TP
+\fB\-width \fIpixels\fR
+Specifies the requested width of the widget. The default is
+\f(CW5i\fR.
+.RE
+.TP
+\fIpathName \fBcrosshairs \fIoperation \fR?\fIarg\fR?
+See the
+.SB "CROSSHAIRS COMPONENT"
+section.
+.TP
+\fIpathName \fBelement \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "ELEMENT COMPONENTS"
+section.
+.TP
+\fIpathName \fBextents \fIitem\fR
+Returns the size of a particular item in the graph. \fIItem\fR must
+be either \f(CWleftmargin\fR, \f(CWrightmargin\fR, \f(CWtopmargin\fR,
+\f(CWbottommargin\fR, \f(CWplotwidth\fR, or \f(CWplotheight\fR.
+.TP
+\fIpathName \fBgrid \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "GRID COMPONENT"
+section.
+.TP
+\fIpathName \fBinvtransform \fIwinX winY\fR
+Performs an inverse coordinate transformation, mapping window
+coordinates back to graph coordinates, using the standard X\-axis and Y\-axis.
+Returns a list of containing the X-Y graph coordinates.
+.TP
+\fIpathName \fBinside \fIx y\fR
+Returns \f(CW1\fR is the designated screen coordinate (\fIx\fR and \fIy\fR)
+is inside the plotting area and \f(CW0\fR otherwise.
+.TP
+\fIpathName \fBlegend \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "LEGEND COMPONENT"
+section.
+.TP
+\fIpathName \fBline\fB operation arg\fR...
+The operation is the same as \fBelement\fR.
+.TP
+\fIpathName \fBmarker \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "MARKER COMPONENTS"
+section.
+.TP
+\fIpathName \fBpostscript \fIoperation \fR?\fIarg\fR?...
+See the
+.SB "POSTSCRIPT COMPONENT"
+section.
+.TP
+\fIpathName \fBsnap \fR?\fIswitches\fR? \fIoutputName\fR
+Takes a snapshot of the graph, saving the output in \fIoutputName\fR.
+The following switches are available.
+.RS
+.TP 1i
+\fB\-format\fR \fIformat\fR
+Specifies how the snapshot is output. \fIFormat\fR may be one of
+the following listed below. The default is \f(CWphoto\fR.
+.RS
+.TP
+\f(CWphoto\fR
+Saves a Tk photo image. \fIOutputName\fR represents the name of a
+Tk photo image that must already have been created.
+.TP
+\f(CWwmf\fR
+Saves an Aldus Placeable Metafile. \fIOutputName\fR represents the
+filename where the metafile is written. If \fIoutputName\fR is
+\f(CWCLIPBOARD\fR, then output is written directly to the Windows
+clipboard. This format is available only under Microsoft Windows.
+.TP
+\f(CWemf\fR
+Saves an Enhanced Metafile. \fIOutputName\fR represents the filename
+where the metafile is written. If \fIoutputName\fR is
+\f(CWCLIPBOARD\fR, then output is written directly to the Windows
+clipboard. This format is available only under Microsoft Windows.
+.RE
+.TP 1i
+\fB\-height\fR \fIsize\fR
+Specifies the height of the graph. \fISize\fR is a screen distance.
+The graph will be redrawn using this dimension, rather than its
+current window height.
+.TP 1i
+\fB\-width\fR \fIsize\fR
+Specifies the width of the graph. \fISize\fR is a screen distance.
+The graph will be redrawn using this dimension, rather than its
+current window width.
+.RE
+.TP
+\fIpathName \fBtransform \fIx y\fR
+Performs a coordinate transformation, mapping graph coordinates to
+window coordinates, using the standard X\-axis and Y\-axis.
+Returns a list containing the X\-Y screen coordinates.
+.TP
+\fIpathName \fBxaxis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fBx2axis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fByaxis \fIoperation\fR ?\fIarg\fR?...
+.TP
+\fIpathName \fBy2axis \fIoperation\fR ?\fIarg\fR?...
+See the
+.SB "AXIS COMPONENTS"
+section.
+.SH "GRAPH COMPONENTS"
+A graph is composed of several components: coordinate axes, data
+elements, legend, grid, cross hairs, postscript, and annotation
+markers. Instead of one big set of configuration options and
+operations, the graph is partitioned, where each component has its own
+configuration options and operations that specifically control that
+aspect or part of the graph.
+.SS "AXIS COMPONENTS"
+Four coordinate axes are automatically created: two X\-coordinate axes
+(\f(CWx\fR and \f(CWx2\fR) and two Y\-coordinate axes (\f(CWy\fR, and
+\f(CWy2\fR). By default, the axis \f(CWx\fR is located in the bottom
+margin, \f(CWy\fR in the left margin, \f(CWx2\fR in the top margin, and
+\f(CWy2\fR in the right margin.
+.PP
+An axis consists of the axis line, title, major and minor ticks, and
+tick labels. Major ticks are drawn at uniform intervals along the
+axis. Each tick is labeled with its coordinate value. Minor ticks
+are drawn at uniform intervals within major ticks.
+.PP
+The range of the axis controls what region of data is plotted.
+Data points outside the minimum and maximum limits of the axis are
+not plotted. By default, the minimum and maximum limits are
+determined from the data, but you can reset either limit.
+.PP
+You can have several axes. To create an axis, invoke
+the axis component and its create operation.
+.CS
+# Create a new axis called "tempAxis"
+\&.g axis create tempAxis
+.CE
+You map data elements to an axis using the element's \-mapy and \-mapx
+configuration options. They specify the coordinate axes an element
+is mapped onto.
+.CS
+# Now map the tempAxis data to this axis.
+\&.g element create "e1" \-xdata $x \-ydata $y \-mapy tempAxis
+.CE
+Any number of axes can be displayed simultaneously. They are drawn in
+the margins surrounding the plotting area. The default axes \f(CWx\fR
+and \f(CWy\fR are drawn in the bottom and left margins. The axes
+\f(CWx2\fR and \f(CWy2\fR are drawn in top and right margins. By
+default, only \f(CWx\fR and \f(CWy\fR are shown. Note that the axes
+can have different scales.
+.PP
+To display a different axis or more than one axis, you invoke one of
+the following components: \fBxaxis\fR, \fByaxis\fR, \fBx2axis\fR, and
+\fBy2axis\fR. Each component has a \fBuse\fR operation that
+designates the axis (or axes) to be drawn in that corresponding
+margin: \fBxaxis\fR in the bottom, \fByaxis\fR in the left,
+\fBx2axis\fR in the top, and \fBy2axis\fR in the right.
+.CS
+# Display the axis tempAxis in the left margin.
+\&.g yaxis use tempAxis
+.CE
+The \fBuse\fR operation takes a list of axis names as its last
+argument. This is the list of axes to be drawn in this margin.
+.PP
+You can configure axes in many ways. The axis scale can be linear or
+logarithmic. The values along the axis can either monotonically
+increase or decrease. If you need custom tick labels, you can specify
+a Tcl procedure to format the label any way you wish. You can control
+how ticks are drawn, by changing the major tick interval or the number
+of minor ticks. You can define non-uniform tick intervals, such as
+for time-series plots.
+.PP
+.TP
+\fIpathName \fBaxis bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for an axis with this
+tag, \fIcommand\fR will be invoked. The syntax is similar to the
+\fBbind\fR command except that it operates on graph axes, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBaxis \fBcget \fIaxisName \fIoption\fR
+Returns the current value of the option given by \fIoption\fR for
+\fIaxisName\fR. \fIOption\fR may be any option described below
+for the axis \fBconfigure\fR operation.
+.TP
+\fIpathName \fBaxis \fBconfigure \fIaxisName \fR?\fIaxisName\fR?... ?\fIoption value\fR?...
+Queries or modifies the configuration options of \fIaxisName\fR.
+Several axes can be changed. If \fIoption\fR isn't specified, a list
+describing all the current options for \fIaxisName\fR is returned. If
+\fIoption\fR is specified, but not \fIvalue\fR, then a list describing
+\fIoption\fR is returned. If one or more \fIoption\fR and \fIvalue\fR
+pairs are specified, then for each pair, the axis option \fIoption\fR
+is set to \fIvalue\fR. The following options are valid for axes.
+.RS
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for the axis. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events for axes are handled. Each tag in the list matching the current event
+sequence will have its Tcl command executed. Implicitly the name of
+the element is always the first tag in the list. The default value is
+\f(CWall\fR.
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the axis and tick labels.
+The default is \f(CWblack\fR.
+.TP
+\fB\-command \fIprefix\fR
+Specifies a Tcl command to be invoked when formatting the axis tick
+labels. \fIPrefix\fR is a string containing the name of a Tcl proc and
+any extra arguments for the procedure. This command is invoked for each
+major tick on the axis. Two additional arguments are passed to the
+procedure: the pathname of the widget and the current the numeric
+value of the tick. The procedure returns the formatted tick label. If
+\f(CW""\fR is returned, no label will appear next to the tick. You can
+get the standard tick labels again by setting \fIprefix\fR to
+\f(CW""\fR. The default is \f(CW""\fR.
+.sp 1
+Please note that this procedure is invoked while the graph is redrawn.
+You may query configuration options. But do not them, because this
+can have unexpected results.
+.TP
+\fB\-descending \fIboolean\fR
+Indicates whether the values along the axis are monotonically increasing or
+decreasing. If \fIboolean\fR is true, the axis values will be
+decreasing. The default is \f(CW0\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates if the axis is displayed. If \fIboolean\fR is false the axis
+will be displayed. Any element mapped to the axis is displayed regardless.
+The default value is \f(CW0\fR.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the axis title should be justified. This matters only
+when the axis title contains more than one line of text. \fIJustify\fR
+must be \f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-limits \fIformatStr\fR
+Specifies a printf-like description to format the minimum and maximum
+limits of the axis. The limits are displayed at the top/bottom or
+left/right sides of the plotting area. \fIFormatStr\fR is a list of
+one or two format descriptions. If one description is supplied, both
+the minimum and maximum limits are formatted in the same way. If two,
+the first designates the format for the minimum limit, the second for
+the maximum. If \f(CW""\fR is given as either description, then
+the that limit will not be displayed. The default is \f(CW""\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the axis and tick lines. The default is \f(CW1\fR
+pixel.
+.TP
+\fB\-logscale \fIboolean\fR
+Indicates whether the scale of the axis is logarithmic or linear. If
+\fIboolean\fR is true, the axis is logarithmic. The default scale is
+linear.
+.TP
+\fB\-loose \fIboolean\fR
+Indicates whether the limits of the axis should fit the data points tightly,
+at the outermost data points, or loosely, at the outer tick intervals.
+If the axis limit is set with the -min or -max option, the axes are
+displayed tightly.
+If \fIboolean\fR is true, the axis range is "loose".
+The default is \f(CW0\fR.
+.TP
+\fB\-majorticks \fImajorList\fR
+Specifies where to display major axis ticks. You can use this option
+to display ticks at non-uniform intervals. \fIMajorList\fR is a list
+of axis coordinates designating the location of major ticks. No
+minor ticks are drawn. If \fImajorList\fR is \f(CW""\fR,
+major ticks will be automatically computed. The default is \f(CW""\fR.
+.TP
+\fB\-max \fIvalue\fR
+Sets the maximum limit of \fIaxisName\fR. Any data point greater
+than \fIvalue\fR is not displayed. If \fIvalue\fR is \f(CW""\fR,
+the maximum limit is calculated using the largest data value.
+The default is \f(CW""\fR.
+.TP
+\fB\-min \fIvalue\fR
+Sets the minimum limit of \fIaxisName\fR. Any data point less than
+\fIvalue\fR is not displayed. If \fIvalue\fR is \f(CW""\fR,
+the minimum limit is calculated using the smallest data value.
+The default is \f(CW""\fR.
+.TP
+\fB\-minorticks \fIminorList\fR
+Specifies where to display minor axis ticks. You can use this option
+to display minor ticks at non-uniform intervals. \fIMinorList\fR is a
+list of real values, ranging from 0.0 to 1.0, designating the placement of
+a minor tick. No minor ticks are drawn if the \fB\-majortick\fR
+option is also set. If \fIminorList\fR is \f(CW""\fR, minor ticks will
+be automatically computed. The default is \f(CW""\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Specifies the how many degrees to rotate the axis tick labels.
+\fITheta\fR is a real value representing the number of degrees
+to rotate the tick labels. The default is \f(CW0.0\fR degrees.
+.TP
+\fB\-scrollcommand \fIcommand\fR
+Specify the prefix for a command used to communicate with scrollbars
+for this axis, such as \fI.sbar set\fP.
+.TP
+\fB\-scrollmax \fIvalue\fR
+Sets the maximum limit of the axis scroll region. If \fIvalue\fR is
+\f(CW""\fR, the maximum limit is calculated using the largest data
+value. The default is \f(CW""\fR.
+.TP
+\fB\-scrollmin \fIvalue\fR
+Sets the minimum limit of axis scroll region. If \fIvalue\fR is
+\f(CW""\fR, the minimum limit is calculated using the smallest data
+value. The default is \f(CW""\fR.
+.TP
+\fB\-showticks \fIboolean\fR
+Indicates whether axis ticks should be drawn. If \fIboolean\fR is
+true, ticks are drawn. If false, only the
+axis line is drawn. The default is \f(CW1\fR.
+.TP
+\fB\-stepsize \fIvalue\fR
+Specifies the interval between major axis ticks. If \fIvalue\fR isn't
+a valid interval (must be less than the axis range),
+the request is ignored and the step size is automatically calculated.
+.TP
+\fB\-subdivisions \fInumber\fR
+Indicates how many minor axis ticks are
+to be drawn. For example, if \fInumber\fR is two, only one minor
+tick is drawn. If \fInumber\fR is one, no minor ticks are
+displayed. The default is \f(CW2\fR.
+.TP
+\fB\-tickfont \fIfontName\fR
+Specifies the font for axis tick labels. The default is
+\f(CW*-Courier-Bold-R-Normal-*-100-*\fR.
+.TP
+\fB\-ticklength \fIpixels\fR
+Sets the length of major and minor ticks (minor ticks are half the
+length of major ticks). If \fIpixels\fR is less than zero, the axis
+will be inverted with ticks drawn pointing towards the plot. The
+default is \f(CW0.1i\fR.
+.TP
+\fB\-title \fItext\fR
+Sets the title of the axis. If \fItext\fR is
+\f(CW""\fR, no axis title will be displayed.
+.TP
+\fB\-titlealternate \fIboolean\fR
+Indicates to display the axis title in its alternate location.
+Normally the axis title is centered along the axis. This option
+places the axis either to the right (horizontal axes) or above
+(vertical axes) the axis. The default is \f(CW0\fR.
+.TP
+\fB\-titlecolor \fIcolor\fR
+Sets the color of the axis title. The default is \f(CWblack\fR.
+.TP
+\fB\-titlefont \fIfontName\fR
+Specifies the font for axis title. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-14-140-*\fR.
+.PP
+Axis configuration options may be also be set by the \fBoption\fR
+command. The resource class is \f(CWAxis\fR. The resource names
+are the names of the axes (such as \f(CWx\fR or \f(CWx2\fR).
+.CS
+option add *Graph.Axis.Color blue
+option add *Graph.x.LogScale true
+option add *Graph.x2.LogScale false
+.CE
+.RE
+.TP
+\fIpathName \fBaxis \fBcreate \fIaxisName \fR?\fIoption value\fR?...
+Creates a new axis by the name \fIaxisName\fR. No axis by the same
+name can already exist. \fIOption\fR and \fIvalue\fR are described
+in above in the axis \fBconfigure\fR operation.
+.TP
+\fIpathName \fBaxis \fBdelete \fR?\fIaxisName\fR?...
+Deletes the named axes. An axis is not really
+deleted until it is not longer in use, so it's safe to delete
+axes mapped to elements.
+.TP
+\fIpathName \fBaxis invtransform \fIaxisName value\fR
+Performs the inverse transformation, changing the screen coordinate
+\fIvalue\fR to a graph coordinate, mapping the value mapped to
+\fIaxisName\fR. Returns the graph coordinate.
+.TP
+\fIpathName \fBaxis limits \fIaxisName\fR
+Returns a list of the minimum and maximum limits for \fIaxisName\fR. The order
+of the list is \f(CWmin max\fR.
+.TP
+\fIpathName \fBaxis names \fR?\fIpattern\fR?...
+Returns a list of axes matching zero or more patterns. If no
+\fIpattern\fR argument is give, the names of all axes are returned.
+.TP
+\fIpathName \fBaxis transform \fIaxisName value\fR
+Transforms the coordinate \fIvalue\fR to a screen coordinate by mapping
+the it to \fIaxisName\fR. Returns the transformed screen coordinate.
+.TP
+\fIpathName \fBaxis view \fIaxisName\fR
+Change the viewable area of this axis. Use as an argument to a scrollbar's "\fI\-command\fR".
+.PP
+The default axes are \f(CWx\fR, \f(CWy\fR, \f(CWx2\fR, and \f(CWy2\fR.
+But you can display more than four axes simultaneously. You can also
+swap in a different axis with \fBuse\fR operation of the special axis
+components: \fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, and \fBy2axis\fR.
+.CS
+\&.g create axis temp
+\&.g create axis time
+\&...
+\&.g xaxis use temp
+\&.g yaxis use time
+.CE
+Only the axes specified for use are displayed on the screen.
+.PP
+The \fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, and \fBy2axis\fR
+components operate on an axis location rather than a specific axis
+like the more general \fBaxis\fR component does. They implicitly
+control the axis that is currently using to that location. By
+default, \fBxaxis\fR uses the \f(CWx\fR axis, \fByaxis\fR uses
+\f(CWy\fR, \fBx2axis\fR uses \f(CWx2\fR, and \fBy2axis\fR uses
+\f(CWy2\fR. When more than one axis is displayed in a margin, it
+represents the first axis displayed.
+.PP
+The following operations are available for axes. They mirror exactly
+the operations of the \fBaxis\fR component. The \fIaxis\fR argument
+must be \fBxaxis\fR, \fBx2axis\fR, \fByaxis\fR, or \fBy2axis\fR. This
+feature is deprecated since more than one axis can now be used a
+margin. You should only use the \fBxaxis\fR, \fBx2axis\fR,
+\fByaxis\fR, and \fBy2axis\fR components with the \fBuse\fR operation.
+For all other operations, use the general \fBaxis\fR component
+instead.
+.TP
+\fIpathName \fIaxis \fBcget \fIoption\fR
+.TP
+\fIpathName \fIaxis \fBconfigure \fR?\fIoption value\fR?...
+.TP
+\fIpathName \fIaxis\fB invtransform \fIvalue\fR
+.TP
+\fIpathName \fIaxis \fBlimits\fR
+.TP
+\fIpathName \fIaxis\fB transform \fIvalue\fR
+.TP
+\fIpathName \fIaxis\fB use \fR?\fIaxisName\fR?
+Designates the axis \fIaxisName\fR is to be displayed at this
+location. \fIAxisName\fR can not be already in use at another location.
+This command returns the name of the axis currently using this location.
+.SS "CROSSHAIRS COMPONENT"
+Cross hairs consist of two intersecting lines (one vertical and one horizontal)
+drawn completely across the plotting area. They are used to position
+the mouse in relation to the coordinate axes. Cross hairs differ from line
+markers in that they are implemented using XOR drawing primitives.
+This means that they can be quickly drawn and erased without redrawing
+the entire graph.
+.PP
+The following operations are available for cross hairs:
+.TP
+\fIpathName \fBcrosshairs cget \fIoption\fR
+Returns the current value of the cross hairs configuration option
+given by \fIoption\fR. \fIOption\fR may be any option
+described below for the cross hairs \fBconfigure\fR operation.
+.TP
+\fIpathName \fBcrosshairs configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options of the cross hairs. If
+\fIoption\fR isn't specified, a list describing all the current
+options for the cross hairs is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the cross hairs option \fIoption\fR is set to
+\fIvalue\fR.
+The following options are available for cross hairs.
+.RS
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the cross hairs. The default is \f(CWblack\fR.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the cross hairs. \fIDashList\fR is a list of up
+to 11 numbers that alternately represent the lengths of the dashes
+and gaps on the cross hair lines. Each number must be between 1 and
+255. If \fIdashList\fR is \f(CW""\fR, the cross hairs will be solid
+lines.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether cross hairs are drawn. If \fIboolean\fR is true,
+cross hairs are not drawn. The default is \f(CWyes\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Set the width of the cross hair lines. The default is \f(CW1\fR.
+.TP
+\fB\-position \fIpos\fR
+Specifies the screen position where the cross hairs intersect.
+\fIPos\fR must be in the form "\fI at x,y\fR", where \fIx\fR and \fIy\fR
+are the window coordinates of the intersection.
+.PP
+Cross hairs configuration options may be also be set by the
+\fBoption\fR command. The resource name and class are
+\f(CWcrosshairs\fR and \f(CWCrosshairs\fR respectively.
+.CS
+option add *Graph.Crosshairs.LineWidth 2
+option add *Graph.Crosshairs.Color red
+.CE
+.RE
+.TP
+\fIpathName \fBcrosshairs off\fR
+Turns off the cross hairs.
+.TP
+\fIpathName \fBcrosshairs on\fR
+Turns on the display of the cross hairs.
+.TP
+\fIpathName \fBcrosshairs toggle\fR
+Toggles the current state of the cross hairs, alternately mapping and
+unmapping the cross hairs.
+.SS "ELEMENT COMPONENTS"
+A data element represents a set of data. It contains x and y vectors
+containing the coordinates of the data points. Elements can be
+displayed with a symbol at each data point and lines connecting the
+points. Elements also control the appearance of the data, such as the
+symbol type, line width, color etc.
+.PP
+When new data elements are created, they are automatically added to a
+list of displayed elements. The display list controls what elements
+are drawn and in what order.
+.PP
+The following operations are available for elements.
+.TP
+\fIpathName \fBelement activate \fIelemName \fR?\fIindex\fR?...
+Specifies the data points of element \fIelemName\fR to be drawn
+using active foreground and background colors. \fIElemName\fR is the
+name of the element and \fIindex\fR is a number representing the index
+of the data point. If no indices are present then all data points
+become active.
+.TP
+\fIpathName \fBelement bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for an element with this
+tag, \fIcommand\fR will be invoked. The syntax is similar to the
+\fBbind\fR command except that it operates on graph elements, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBelement cget \fIelemName \fIoption\fR
+Returns the current value of the element configuration option given by
+\fIoption\fR. \fIOption\fR may be any of the options described below
+for the element \fBconfigure\fR operation.
+.TP
+\fIpathName \fBelement closest \fIx y\fR ?\fIoption value\fR?... ?\fIelemName\fR?...
+Searches for the data point closest to the window coordinates \fIx\fR
+and \fIy\fR. By default, all elements are searched. Hidden elements
+(see the \fB\-hide\fR option is false) are ignored. You can limit the
+search by specifying only the elements you want to be considered.
+\fIElemName\fR must be the name of an element that can not be hidden.
+It returns a key-value list containing the name of the closest element,
+the index of the closest data point, and the graph-coordinates of the point.
+Returns \f(CW""\fR, if no data point within the threshold distance
+can be found. The following
+\fIoption\fR\-\fIvalue\fR pairs are available.
+.RS
+.TP
+\fB\-along \fIdirection\fR
+Search for the closest element using the following criteria:
+.RS
+.TP
+\f(CWx\fR
+Find closest element vertically from the given X-coordinate.
+.TP
+\f(CWy\fR
+Find the closest element horizontally from the given Y-coordinate.
+.TP
+\f(CWboth\fR
+Find the closest element for the given point (using both the X and Y
+coordinates).
+.RE
+.TP
+\fB\-halo \fIpixels\fR
+Specifies a threshold distance where selected data points are ignored.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+If this option isn't specified, then it defaults to the value of the
+graph's \fB\-halo\fR option.
+.TP
+\fB\-interpolate \fIstring\fR
+Indicates whether to consider projections that lie along the line segments
+connecting data points when searching for the closest point.
+The default value is \f(CW0\fR. The values for \fIstring\fR are
+described below.
+.RS
+.TP 1.25i
+\f(CWno\fR
+Search only for the closest data point.
+.TP
+\f(CWyes\fR
+Search includes projections that lie along the
+line segments connecting the data points.
+.RE
+.RE
+.TP
+\fIpathName \fBelement configure \fIelemName \fR?\fIelemName\fR... ?\fIoption value\fR?...
+Queries or modifies the configuration options for elements. Several
+elements can be modified at the same time. If \fIoption\fR isn't
+specified, a list describing all the current options for
+\fIelemName\fR is returned. If \fIoption\fR is specified, but not
+\fIvalue\fR, then a list describing the option \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the element option \fIoption\fR is set
+to \fIvalue\fR. The following options are valid for elements.
+.RS
+.TP
+\fB\-activepen \fIpenName\fR
+Specifies pen to use to draw active element. If \fIpenName\fR is
+\f(CW""\fR, no active elements will be drawn. The default is
+\f(CWactiveLine\fR.
+.TP
+\fB\-areabackground \fIcolor\fR
+Specifies the background color of the area under the curve. The
+background area color is drawn only for bitmaps (see the
+\fB\-areapattern\fR option). If \fIcolor\fR is \f(CW""\fR, the
+background is transparent. The default is \f(CWblack\fR.
+.TP
+\fB\-areaforeground \fIcolor\fR
+Specifies the foreground color of the area under the curve.
+The default is \f(CWblack\fR.
+.TP
+\fB\-areapattern \fIpattern\fR
+Specifies how to fill the area under the curve. \fIPattern\fR may be
+the name of a Tk bitmap, \f(CWsolid\fR, or \f(CW""\fR. If "solid",
+then the area under the curve is drawn with the color designated by
+the \fB\-areaforeground\fR option. If a bitmap, then the bitmap is
+stippled across the area. Here the bitmap colors are controlled by the
+\fB\-areaforeground\fR and \fB\-areabackground\fR options. If
+\fIpattern\fR is \f(CW""\fR, no filled area is drawn. The default is
+\f(CW""\fR.
+.TP
+\fB\-areatile \fIimage\fR
+Specifies the name of a Tk image to be used to tile the area under the
+curve. This option supersedes the \fB\-areapattern\fR option.
+\fIImage\fR must be a photo image. If \fIimage\fR is \f(CW""\fR, no
+tiling is performed. The default is \f(CW""\fR.
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for the element. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events are handled for elements. Each tag in the list matching the
+current event
+sequence will have its Tcl command executed. Implicitly the name of
+the element is always the first tag in the list. The default value is
+\f(CWall\fR.
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the traces connecting the data points.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of element line. \fIDashList\fR is a list of up to
+11 numbers that alternately represent the lengths of the dashes and
+gaps on the element line. Each number must be between 1 and 255. If
+\fIdashList\fR is \f(CW""\fR, the lines will be solid.
+.TP
+\fB\-data \fIcoordList\fR
+Specifies the X\-Y coordinates of the data. \fICoordList\fR is a
+list of numeric expressions representing the X\-Y coordinate pairs
+of each data point.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the interior color of symbols. If \fIcolor\fR is \f(CW""\fR, then
+the interior of the symbol is transparent. If \fIcolor\fR is
+\f(CWdefcolor\fR, then the color will be the same as the \fB\-color\fR
+option. The default is \f(CWdefcolor\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the element is displayed.
+The default is \f(CWno\fR.
+.TP
+\fB\-label \fItext\fR
+Sets the element's label in the legend. If \fItext\fR
+is \f(CW""\fR, the element will have no entry in the legend.
+The default label is the element's name.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the connecting lines between data points. If
+\fIpixels\fR is \f(CW0\fR, no connecting lines will be drawn between
+symbols. The default is \f(CW0\fR.
+.TP
+\fB\-mapx \fIxAxis\fR
+Selects the X\-axis to map the element's X\-coordinates onto.
+\fIXAxis\fR must be the name of an axis. The default is \f(CWx\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Selects the Y\-axis to map the element's Y\-coordinates onto.
+\fIYAxis\fR must be the name of an axis. The default is \f(CWy\fR.
+.TP
+\fB\-offdash \fIcolor\fR
+Sets the color of the stripes when traces are dashed (see the
+\fB\-dashes\fR option). If \fIcolor\fR is \f(CW""\fR, then the "off"
+pixels will represent gaps instead of stripes. If \fIcolor\fR is
+\f(CWdefcolor\fR, then the color will be the same as the \fB\-color\fR
+option. The default is \f(CWdefcolor\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color or the outline around each symbol. If \fIcolor\fR is
+\f(CW""\fR, then no outline is drawn. If \fIcolor\fR is \f(CWdefcolor\fR,
+then the color will be the same as the \fB\-color\fR option. The
+default is \f(CWdefcolor\fR.
+.TP
+\fB\-pen \fIpenname\fR
+Set the pen to use for this element.
+.TP
+\fB\-outlinewidth \fIpixels\fR
+Sets the width of the outline bordering each symbol. If \fIpixels\fR
+is \f(CW0\fR, no outline will be drawn. The default is \f(CW1\fR.
+.TP
+\fB\-pixels \fIpixels\fR
+Sets the size of symbols. If \fIpixels\fR is \f(CW0\fR, no symbols will
+be drawn. The default is \f(CW0.125i\fR.
+.TP
+\fB\-scalesymbols \fIboolean\fR
+If \fIboolean\fR is true, the size of the symbols
+drawn for \fIelemName\fR will change with scale of the X\-axis and Y\-axis.
+At the time this option is set, the current ranges of the axes are
+saved as the normalized scales (i.e scale factor is 1.0) and the
+element is drawn at its designated size (see the \fB\-pixels\fR
+option). As the scale of the axes change, the symbol will be scaled
+according to the smaller of the X\-axis and Y\-axis scales. If \fIboolean\fR
+is false, the element's symbols are drawn at the designated size,
+regardless of axis scales. The default is \f(CW0\fR.
+.TP
+\fB\-smooth \fIsmooth\fR
+Specifies how connecting line segments are drawn between data points.
+\fISmooth\fR can be either \f(CWlinear\fR, \f(CWstep\fR, \f(CWnatural\fR, or
+\f(CWquadratic\fR. If \fIsmooth\fR is \f(CWlinear\fR, a single line
+segment is drawn, connecting both data points. When \fIsmooth\fR is
+\f(CWstep\fR, two line segments are drawn. The first is a horizontal
+line segment that steps the next X\-coordinate. The second is a
+vertical line, moving to the next Y\-coordinate. Both \fInatural\fR and
+\fIquadratic\fR generate multiple segments between data points. If
+\fInatural\fR, the segments are generated using a cubic spline. If
+\fIquadratic\fR, a quadratic spline is used. The default is
+\fIlinear\fR.
+.TP
+\fB\-styles \fIstyleList\fR
+Specifies what pen to use based on the range of weights given.
+\fIStyleList\fR is a list of style specifications. Each style
+specification, in turn, is a list consisting of a pen name, and
+optionally a minimum and maximum range. Data points whose weight (see
+the \fB\-weight\fR option) falls in this range, are drawn with this
+pen. If no range is specified it defaults to the index of the pen in
+the list. Note that this affects only symbol attributes. Line
+attributes, such as line width, dashes, etc. are ignored.
+.TP
+\fB\-symbol \fIsymbol\fR
+Specifies the symbol for data points. \fISymbol\fR can be either
+\f(CWsquare\fR, \f(CWcircle\fR, \f(CWdiamond\fR, \f(CWplus\fR, \f(CWcross\fR,
+\f(CWsplus\fR, \f(CWscross\fR, \f(CWtriangle\fR, \f(CW""\fR (where no symbol
+is drawn), or a bitmap. Bitmaps are specified as "\fIsource\fR
+?\fImask\fR?", where \fIsource\fR is the name of the bitmap, and
+\fImask\fR is the bitmap's optional mask. The default is
+\f(CWcircle\fR.
+.TP
+\fB\-trace \fIdirection\fR
+Indicates whether connecting lines between data points (whose
+X\-coordinate values are either increasing or decreasing) are drawn.
+\fIDirection\fR
+must be \f(CWincreasing\fR, \f(CWdecreasing\fR, or \f(CWboth\fR. For
+example, if \fIdirection\fR is \f(CWincreasing\fR, connecting lines will
+be drawn only between those data points where X\-coordinate values are
+monotonically increasing. If \fIdirection\fR is \f(CWboth\fR,
+connecting lines will be draw between all data points. The default is
+\f(CWboth\fR.
+.TP
+\fB\-weights \fIwVec\fR
+Specifies the weights of the individual data points. This,
+with the list pen styles (see the \fB\-styles\fR option),
+controls how data points are drawn. \fIWVec\fR is the name of a BLT
+vector or a list of numeric expressions representing the weights for
+each data point.
+.TP
+\fB\-xdata \fIxVec\fR
+Specifies the X\-coordinates of the data. \fIXVec\fR is the name of
+a BLT vector or a list of numeric expressions.
+.TP
+\fB\-ydata \fIyVec\fR
+Specifies the Y\-coordinates of the data. \fIYVec\fR is the name of
+a BLT vector or a list of numeric expressions.
+.PP
+Element configuration options may also be set by the \fBoption\fR
+command. The resource class is \f(CWElement\fR. The resource name is
+the name of the element.
+.CS
+option add *Graph.Element.symbol line
+option add *Graph.e1.symbol line
+.CE
+.RE
+.TP
+\fIpathName \fBelement create \fIelemName\fR ?\fIoption value\fR?...
+Creates a new element \fIelemName\fR. It's an error is
+an element \fIelemName\fR already exists. If
+additional arguments are present, they specify options valid for
+the element \fBconfigure\fR operation.
+.TP
+\fIpathName \fBelement deactivate \fIelemName\fR ?\fIelemName\fR?...
+Deactivates all the elements matching \fIpattern\fR.
+Elements whose names match any of the patterns given are redrawn using
+their normal colors.
+.TP
+\fIpathName \fBelement delete\fR ?\fIelemName\fR?...
+Deletes all the named elements. The graph is automatically redrawn.
+.TP
+\fIpathName \fBelement exists \fIelemName\fR
+Returns \f(CW1\fR if an element \fIelemName\fR currently exists and
+\f(CW0\fR otherwise.
+.TP
+\fIpathName \fBelement names \fR?\fIpattern\fR?...
+Returns the elements matching one or more pattern. If no
+\fIpattern\fR is given, the names of all elements is returned.
+.TP
+\fIpathName \fBelement show\fR ?\fInameList\fR?
+Queries or modifies the element display list. The element display
+list designates the elements drawn and in what
+order. \fINameList\fR is a list of elements to be displayed in the
+order they are named. If there is no \fInameList\fR argument,
+the current display list is returned.
+.TP
+\fIpathName \fBelement type\fR \fIelemName\fR
+Returns the type of \fIelemName\fR.
+If the element is a bar element, the commands returns the string
+\f(CW"bar"\fR, otherwise it returns \f(CW"line"\fR.
+.CE
+.SS "GRID COMPONENT"
+Grid lines extend from the major and minor ticks of each axis
+horizontally or vertically across the plotting area. The following
+operations are available for grid lines.
+.TP
+\fIpathName \fBgrid cget \fIoption\fR
+Returns the current value of the grid line configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described below
+for the grid \fBconfigure\fR operation.
+.TP
+\fIpathName \fBgrid configure\fR ?\fIoption value\fR?...
+Queries or modifies the configuration options for grid lines. If
+\fIoption\fR isn't specified, a list describing all the current
+grid options for \fIpathName\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the grid line option \fIoption\fR is set to
+\fIvalue\fR. The following options are valid for grid lines.
+.RS
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the grid lines. The default is \f(CWblack\fR.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the grid lines. \fIDashList\fR is a list of up
+to 11 numbers that alternately represent the lengths of the dashes
+and gaps on the grid lines. Each number must be between 1 and 255.
+If \fIdashList\fR is \f(CW""\fR, the grid will be solid lines.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the grid should be drawn. If \fIboolean\fR
+is true, grid lines are not shown. The default is \f(CWyes\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of grid lines. The default width is \f(CW1\fR.
+.TP
+\fB\-mapx \fIxAxis\fR
+Specifies the X\-axis to display grid lines. \fIXAxis\fR
+must be the name of an axis or \f(CW""\fR for no grid lines.
+The default is \f(CW""\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Specifies the Y\-axis to display grid lines. \fIYAxis\fR
+must be the name of an axis or \f(CW""\fR for no grid lines.
+The default is \f(CWy\fR.
+.TP
+\fB\-minor \fIboolean\fR
+Indicates whether the grid lines should be drawn for minor ticks.
+If \fIboolean\fR is true, the lines will appear at
+minor tick intervals. The default is \f(CW1\fR.
+.PP
+Grid configuration options may also be set by the
+\fBoption\fR command. The resource name and class are \f(CWgrid\fR and
+\f(CWGrid\fR respectively.
+.CS
+option add *Graph.grid.LineWidth 2
+option add *Graph.Grid.Color black
+.CE
+.RE
+.TP
+\fIpathName \fBgrid off\fR
+Turns off the display the grid lines.
+.TP
+\fIpathName \fBgrid on\fR
+Turns on the display the grid lines.
+.TP
+\fIpathName \fBgrid toggle\fR
+Toggles the display of the grid.
+.SS "LEGEND COMPONENT"
+The legend displays a list of the data elements. Each entry consists
+of the element's symbol and label. The legend can appear in any
+margin (the default location is in the right margin). It
+can also be positioned anywhere within the plotting area.
+.PP
+The following operations are valid for the legend.
+.TP
+\fIpathName \fBlegend activate \fIpattern\fR...
+Selects legend entries to be drawn using the active legend colors and relief.
+All entries whose element names match \fIpattern\fR are selected. To
+be selected, the element name must match only one \fIpattern\fR.
+.TP
+\fIpathName \fBlegend bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for a legend entry with this
+tag, \fIcommand\fR will be invoked. Implicitly the element names
+in the entry are tags. The syntax is similar to the
+\fBbind\fR command except that it operates on legend entries, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBlegend cget \fIoption\fR
+Returns the current value of a legend configuration option.
+\fIOption\fR may be any option described below in the
+legend \fBconfigure\fR operation.
+.TP
+\fIpathName \fBlegend configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options for the legend. If
+\fIoption\fR isn't specified, a list describing the current
+legend options for \fIpathName\fR is returned. If \fIoption\fR is
+specified, but not \fIvalue\fR, then a list describing \fIoption\fR is
+returned. If one or more \fIoption\fR and \fIvalue\fR pairs are
+specified, then for each pair, the legend option \fIoption\fR is set
+to \fIvalue\fR. The following options are valid for the legend.
+.RS
+.TP
+\fB\-activebackground \fIcolor\fR
+Sets the background color for active legend entries. All legend
+entries marked active (see the legend \fBactivate\fR operation) are
+drawn using this background color.
+.TP
+\fB\-activeborderwidth \fIpixels\fR
+Sets the width of the 3-D border around the outside edge of the active legend
+entries. The default is \f(CW2\fR.
+.TP
+\fB\-activeforeground \fIcolor\fR
+Sets the foreground color for active legend entries. All legend
+entries marked as active (see the legend \fBactivate\fR operation) are
+drawn using this foreground color.
+.TP
+\fB\-activerelief \fIrelief\fR
+Specifies the 3-D effect desired for active legend entries.
+\fIRelief\fR denotes how the interior of the entry should appear
+relative to the legend; for example, \f(CWraised\fR means the entry
+should appear to protrude from the legend, relative to the surface of
+the legend. The default is \f(CWflat\fR.
+.TP
+\fB\-anchor \fIanchor\fR
+Tells how to position the legend relative to the positioning point for
+the legend. This is dependent on the value of the \fB\-position\fR
+option. The default is \f(CWcenter\fR.
+.RS
+.TP 1.25i
+\f(CWleft\fR or \f(CWright\fR
+The anchor describes how to position the legend vertically.
+.TP
+\f(CWtop\fR or \f(CWbottom\fR
+The anchor describes how to position the legend horizontally.
+.TP
+\f(CW at x,y\fR
+The anchor specifies how to position the legend relative to the
+positioning point. For example, if \fIanchor\fR is \f(CWcenter\fR then
+the legend is centered on the point; if \fIanchor\fR is \f(CWn\fR then
+the legend will be drawn such that the top center point of the
+rectangular region occupied by the legend will be at the positioning
+point.
+.TP
+\f(CWplotarea\fR
+The anchor specifies how to position the legend relative to the
+plotting area. For example, if \fIanchor\fR is \f(CWcenter\fR then the
+legend is centered in the plotting area; if \fIanchor\fR is \f(CWne\fR
+then the legend will be drawn such that occupies the upper right
+corner of the plotting area.
+.RE
+.TP
+\fB\-background \fIcolor\fR
+Sets the background color of the legend. If \fIcolor\fR is \f(CW""\fR,
+the legend background with be transparent.
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for legend entries. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events are handled for legend entries. Each tag in the list matching
+the current event sequence will have its Tcl command executed. The
+default value is \f(CWall\fR.
+.TP
+\fB\-borderwidth \fIpixels\fR
+Sets the width of the 3-D border around the outside edge of the legend (if
+such border is being drawn; the \fBrelief\fR option determines this).
+The default is \f(CW2\fR pixels.
+.TP
+\fB\-font \fIfontName\fR
+\fIFontName\fR specifies a font to use when drawing the labels of each
+element into the legend. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-12-120-*\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Sets the foreground color of the text drawn for the element's label.
+The default is \f(CWblack\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the legend should be displayed. If \fIboolean\fR is
+true, the legend will not be draw. The default is \f(CWno\fR.
+.TP
+\fB\-ipadx \fIpad\fR
+Sets the amount of internal padding to be added to the width of each
+legend entry. \fIPad\fR can be a list of one or two screen distances. If
+\fIpad\fR has two elements, the left side of the legend entry is
+padded by the first distance and the right side by the second. If
+\fIpad\fR is just one distance, both the left and right sides are padded
+evenly. The default is \f(CW2\fR.
+.TP
+\fB\-ipady \fIpad\fR
+Sets an amount of internal padding to be added to the height of each
+legend entry. \fIPad\fR can be a list of one or two screen distances. If
+\fIpad\fR has two elements, the top of the entry is padded by the
+first distance and the bottom by the second. If \fIpad\fR is just
+one distance, both the top and bottom of the entry are padded evenly.
+The default is \f(CW2\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the padding to the left and right exteriors of the legend.
+\fIPad\fR can be a list of one or two screen distances. If \fIpad\fR
+has two elements, the left side of the legend is padded by the first
+distance and the right side by the second. If \fIpad\fR has just one
+distance, both the left and right sides are padded evenly. The
+default is \f(CW4\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the padding above and below the legend. \fIPad\fR can be a list
+of one or two screen distances. If \fIpad\fR has two elements, the area above
+the legend is padded by the first distance and the area below by the
+second. If \fIpad\fR is just one distance, both the top and
+bottom areas are padded evenly. The default is \f(CW0\fR.
+.TP
+\fB\-position \fIpos\fR
+Specifies where the legend is drawn. The
+\fB\-anchor\fR option also affects where the legend is positioned. If
+\fIpos\fR is \f(CWleft\fR, \f(CWleft\fR, \f(CWtop\fR, or \f(CWbottom\fR, the
+legend is drawn in the specified margin. If \fIpos\fR is
+\f(CWplotarea\fR, then the legend is drawn inside the plotting area at a
+particular anchor. If \fIpos\fR is in the form "\fI at x,y\fR", where
+\fIx\fR and \fIy\fR are the window coordinates, the legend is drawn in
+the plotting area at the specified coordinates. The default is
+\f(CWright\fR.
+.TP
+\fB\-raised \fIboolean\fR
+Indicates whether the legend is above or below the data elements. This
+matters only if the legend is in the plotting area. If \fIboolean\fR
+is true, the legend will be drawn on top of any elements that may
+overlap it. The default is \f(CWno\fR.
+.TP
+\fB\-relief \fIrelief\fR
+Specifies the 3-D effect for the border around the legend.
+\fIRelief\fR specifies how the interior of the legend should appear
+relative to the graph; for example, \f(CWraised\fR means the legend
+should appear to protrude from the graph, relative to the surface of
+the graph. The default is \f(CWsunken\fR.
+.PP
+Legend configuration options may also be set by the \fBoption\fR
+command. The resource name and class are \f(CWlegend\fR and
+\f(CWLegend\fR respectively.
+.CS
+option add *Graph.legend.Foreground blue
+option add *Graph.Legend.Relief raised
+.CE
+.RE
+.TP
+\fIpathName \fBlegend deactivate \fIpattern\fR...
+Selects legend entries to be drawn using the normal legend colors and
+relief. All entries whose element names match \fIpattern\fR are
+selected. To be selected, the element name must match only one
+\fIpattern\fR.
+.TP
+\fIpathName \fBlegend get \fIpos\fR
+Returns the name of the element whose entry is at the screen position
+\fIpos\fR in the legend. \fIPos\fR must be in the form "\fI at x,y\fR",
+where \fIx\fR and \fIy\fR are window coordinates. If the given
+coordinates do not lie over a legend entry, \f(CW""\fR is returned.
+.SS "PEN COMPONENTS"
+Pens define attributes (both symbol and line style) for elements.
+Pens mirror the configuration options of data elements that pertain to
+how symbols and lines are drawn. Data elements use pens to determine
+how they are drawn. A data element may use several pens at once. In
+this case, the pen used for a particular data point is determined from
+each element's weight vector (see the element's \fB\-weight\fR and
+\fB\-style\fR options).
+.PP
+One pen, called \f(CWactiveLine\fR, is automatically created.
+It's used as the default active pen for elements. So you can change
+the active attributes for all elements by simply reconfiguring this
+pen.
+.CS
+\&.g pen configure "activeLine" -color green
+.CE
+You can create and use several pens. To create a pen, invoke
+the pen component and its create operation.
+.CS
+\&.g pen create myPen
+.CE
+You map pens to a data element using either the element's
+\fB\-pen\fR or \fB\-activepen\fR options.
+.CS
+\&.g element create "line1" -xdata $x -ydata $tempData \\
+ -pen myPen
+.CE
+An element can use several pens at once. This is done by specifying
+the name of the pen in the element's style list (see the
+\fB\-styles\fR option).
+.CS
+\&.g element configure "line1" -styles { myPen 2.0 3.0 }
+.CE
+This says that any data point with a weight between 2.0 and 3.0
+is to be drawn using the pen \f(CWmyPen\fR. All other points
+are drawn with the element's default attributes.
+.PP
+The following operations are available for pen components.
+.PP
+.TP
+\fIpathName \fBpen \fBcget \fIpenName \fIoption\fR
+Returns the current value of the option given by \fIoption\fR for
+\fIpenName\fR. \fIOption\fR may be any option described below
+for the pen \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpen \fBconfigure \fIpenName \fR?\fIpenName\fR... ?\fIoption value\fR?...
+Queries or modifies the configuration options of
+\fIpenName\fR. Several pens can be modified at once. If \fIoption\fR
+isn't specified, a list describing the current options for
+\fIpenName\fR is returned. If \fIoption\fR is specified, but not
+\fIvalue\fR, then a list describing \fIoption\fR is returned. If one
+or more \fIoption\fR and \fIvalue\fR pairs are specified, then for
+each pair, the pen option \fIoption\fR is set to \fIvalue\fR. The
+following options are valid for pens.
+.RS
+.TP
+\fB\-color \fIcolor\fR
+Sets the color of the traces connecting the data points.
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of element line. \fIDashList\fR is a list of up to
+11 numbers that alternately represent the lengths of the dashes and
+gaps on the element line. Each number must be between 1 and 255. If
+\fIdashList\fR is \f(CW""\fR, the lines will be solid.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the interior color of symbols. If \fIcolor\fR is \f(CW""\fR, then
+the interior of the symbol is transparent. If \fIcolor\fR is
+\f(CWdefcolor\fR, then the color will be the same as the \fB\-color\fR
+option. The default is \f(CWdefcolor\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the connecting lines between data points. If
+\fIpixels\fR is \f(CW0\fR, no connecting lines will be drawn between
+symbols. The default is \f(CW0\fR.
+.TP
+\fB\-offdash \fIcolor\fR
+Sets the color of the stripes when traces are dashed (see the
+\fB\-dashes\fR option). If \fIcolor\fR is \f(CW""\fR, then the "off"
+pixels will represent gaps instead of stripes. If \fIcolor\fR is
+\f(CWdefcolor\fR, then the color will be the same as the \fB\-color\fR
+option. The default is \f(CWdefcolor\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color or the outline around each symbol. If \fIcolor\fR is
+\f(CW""\fR, then no outline is drawn. If \fIcolor\fR is \f(CWdefcolor\fR,
+then the color will be the same as the \fB\-color\fR option. The
+default is \f(CWdefcolor\fR.
+.TP
+\fB\-outlinewidth \fIpixels\fR
+Sets the width of the outline bordering each symbol. If \fIpixels\fR
+is \f(CW0\fR, no outline will be drawn. The default is \f(CW1\fR.
+.TP
+\fB\-pixels \fIpixels\fR
+Sets the size of symbols. If \fIpixels\fR is \f(CW0\fR, no symbols will
+be drawn. The default is \f(CW0.125i\fR.
+.TP
+\fB\-symbol \fIsymbol\fR
+Specifies the symbol for data points. \fISymbol\fR can be either
+\f(CWsquare\fR, \f(CWcircle\fR, \f(CWdiamond\fR, \f(CWplus\fR, \f(CWcross\fR,
+\f(CWsplus\fR, \f(CWscross\fR, \f(CWtriangle\fR, \f(CW""\fR (where no symbol
+is drawn), or a bitmap. Bitmaps are specified as "\fIsource\fR
+?\fImask\fR?", where \fIsource\fR is the name of the bitmap, and
+\fImask\fR is the bitmap's optional mask. The default is
+\f(CWcircle\fR.
+.TP
+\fB\-type \fIelemType\fR
+Specifies the type of element the pen is to be used with.
+This option should only be employed when creating the pen. This
+is for those that wish to mix different types of elements (bars and
+lines) on the same graph. The default type is "line".
+.PP
+Pen configuration options may be also be set by the \fBoption\fR
+command. The resource class is \f(CWPen\fR. The resource names
+are the names of the pens.
+.CS
+option add *Graph.Pen.Color blue
+option add *Graph.activeLine.color green
+.CE
+.RE
+.TP
+\fIpathName \fBpen \fBcreate \fIpenName \fR?\fIoption value\fR?...
+Creates a new pen by the name \fIpenName\fR. No pen by the same
+name can already exist. \fIOption\fR and \fIvalue\fR are described
+in above in the pen \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpen \fBdelete \fR?\fIpenName\fR?...
+Deletes the named pens. A pen is not really
+deleted until it is not longer in use, so it's safe to delete
+pens mapped to elements.
+.TP
+\fIpathName \fBpen names \fR?\fIpattern\fR?...
+Returns a list of pens matching zero or more patterns. If no
+\fIpattern\fR argument is give, the names of all pens are returned.
+.SS "POSTSCRIPT COMPONENT"
+The graph can generate encapsulated PostScript output. There
+are several configuration options you can specify to control how the
+plot will be generated. You can change the page dimensions and
+borders. The plot itself can be scaled, centered, or rotated to
+landscape. The PostScript output can be written directly to a file or
+returned through the interpreter.
+.PP
+The following postscript operations are available.
+.TP
+\fIpathName \fBpostscript cget \fIoption\fR
+Returns the current value of the postscript option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below for the postscript \fBconfigure\fR operation.
+.TP
+\fIpathName \fBpostscript configure \fR?\fIoption value\fR?...
+Queries or modifies the configuration options for PostScript
+generation. If \fIoption\fR isn't specified, a list describing
+the current postscript options for \fIpathName\fR is returned. If
+\fIoption\fR is specified, but not \fIvalue\fR, then a list describing
+\fIoption\fR is returned. If one or more \fIoption\fR and \fIvalue\fR
+pairs are specified, then for each pair, the postscript option
+\fIoption\fR is set to \fIvalue\fR. The following postscript options
+are available.
+.RS
+.TP
+\fB\-center \fIboolean\fR
+Indicates whether the plot should be centered on the PostScript page. If
+\fIboolean\fR is false, the plot will be placed in the upper left
+corner of the page. The default is \f(CW1\fR.
+.TP
+\fB\-colormap \fIvarName\fR
+\fIVarName\fR must be the name of a global array variable that
+specifies a color mapping from the X color name to PostScript. Each
+element of \fIvarName\fR must consist of PostScript code to set a
+particular color value (e.g. ``\f(CW1.0 1.0 0.0 setrgbcolor\fR''). When
+generating color information in PostScript, the array variable \fIvarName\fR
+is checked if an element of the name as the color exists. If so, it uses
+its value as the PostScript
+command to set the color. If this option hasn't been specified, or if
+there isn't an entry in \fIvarName\fR for a given color, then it uses
+the red, green, and blue intensities from the X color.
+.TP
+\fB\-colormode \fImode\fR
+Specifies how to output color information. \fIMode\fR must be either
+\f(CWcolor\fR (for full color output), \f(CWgray\fR (convert all colors to
+their gray-scale equivalents) or \f(CWmono\fR (convert foreground colors
+to black and background colors to white). The default mode is
+\f(CWcolor\fR.
+.TP
+\fB\-fontmap \fIvarName\fR
+\fIVarName\fR must be the name of a global array variable that
+specifies a font mapping from the X font name to PostScript. Each
+element of \fIvarName\fR must consist of a Tcl list with one or two
+elements; the name and point size of a PostScript font.
+When outputting PostScript commands for a particular font, the array
+variable \fIvarName\fR is checked to see if an element by the
+specified font exists. If there is such an element, then the font
+information contained in that element is used in the PostScript
+output. (If the point size is omitted from the list, the point size
+of the X font is used). Otherwise the X font is examined in an
+attempt to guess what PostScript font to use. This works only for
+fonts whose foundry property is \fIAdobe\fR (such as Times, Helvetica,
+Courier, etc.). If all of this fails then the font defaults to
+\f(CWHelvetica-Bold\fR.
+.TP
+\fB\-decorations \fIboolean\fR
+Indicates whether PostScript commands to generate color backgrounds and 3-D
+borders will be output. If \fIboolean\fR is false, the background will be
+white and no 3-D borders will be generated. The
+default is \f(CW1\fR.
+.TP
+\fB\-height \fIpixels\fR
+Sets the height of the plot. This lets you print the graph with a
+height different from the one drawn on the screen. If
+\fIpixels\fR is 0, the height is the same as the widget's height.
+The default is \f(CW0\fR.
+.TP
+\fB\-landscape \fIboolean\fR
+If \fIboolean\fR is true, this specifies the printed area is to be
+rotated 90 degrees. In non-rotated output the X\-axis of the printed
+area runs along the short dimension of the page (``portrait''
+orientation); in rotated output the X\-axis runs along the long
+dimension of the page (``landscape'' orientation). Defaults to
+\f(CW0\fR.
+.TP
+\fB\-maxpect \fIboolean\fR
+Indicates to scale the plot so that it fills the PostScript page.
+The aspect ratio of the graph is still retained. The default is
+\f(CW0\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the horizontal padding for the left and right page borders. The
+borders are exterior to the plot. \fIPad\fR can be a list of one or
+two screen distances. If \fIpad\fR has two elements, the left border is padded
+by the first distance and the right border by the second. If
+\fIpad\fR has just one distance, both the left and right borders are
+padded evenly. The default is \f(CW1i\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the vertical padding for the top and bottom page borders. The
+borders are exterior to the plot. \fIPad\fR can be a list of one or
+two screen distances. If \fIpad\fR has two elements, the top border is padded
+by the first distance and the bottom border by the second. If
+\fIpad\fR has just one distance, both the top and bottom borders are
+padded evenly. The default is \f(CW1i\fR.
+.TP
+\fB\-paperheight \fIpixels\fR
+Sets the height of the postscript page. This can be used to select
+between different page sizes (letter, A4, etc). The default height is
+\f(CW11.0i\fR.
+.TP
+\fB\-paperwidth \fIpixels\fR
+Sets the width of the postscript page. This can be used to select
+between different page sizes (letter, A4, etc). The default width is
+\f(CW8.5i\fR.
+.TP
+\fB\-width \fIpixels\fR
+Sets the width of the plot. This lets you generate a plot
+of a width different from that of the widget. If \fIpixels\fR
+is 0, the width is the same as the widget's width. The default is
+\f(CW0\fR.
+.PP
+Postscript configuration options may be also be set by the
+\fBoption\fR command. The resource name and class are
+\f(CWpostscript\fR and \f(CWPostscript\fR respectively.
+.CS
+option add *Graph.postscript.Decorations false
+option add *Graph.Postscript.Landscape true
+.CE
+.RE
+.TP
+\fIpathName \fBpostscript output \fR?\fIfileName\fR? ?\fIoption value\fR?...
+Outputs a file of encapsulated PostScript. If a
+\fIfileName\fR argument isn't present, the command returns the
+PostScript. If any \fIoption-value\fR pairs are present, they set
+configuration options controlling how the PostScript is generated.
+\fIOption\fR and \fIvalue\fR can be anything accepted by the
+postscript \fBconfigure\fR operation above.
+.SS "MARKER COMPONENTS"
+Markers are simple drawing procedures used to annotate or highlight
+areas of the graph. Markers have various types: text strings,
+bitmaps, images, connected lines, windows, or polygons. They can be
+associated with a particular element, so that when the element is
+hidden or un-hidden, so is the marker. By default, markers are the
+last items drawn, so that data elements will appear in
+behind them. You can change this by configuring the \fB\-under\fR
+option.
+.PP
+Markers, in contrast to elements, don't affect the scaling of the
+coordinate axes. They can also have \fIelastic\fR coordinates
+(specified by \f(CW-Inf\fR and \f(CWInf\fR respectively) that translate
+into the minimum or maximum limit of the axis. For example, you can
+place a marker so it always remains in the lower left corner of the
+plotting area, by using the coordinates \f(CW-Inf\fR,\f(CW-Inf\fR.
+.PP
+The following operations are available for markers.
+.TP
+\fIpathName \fBmarker after \fImarkerId\fR ?\fIafterId\fR?
+Changes the order of the markers, drawing the first
+marker after the second. If no second \fIafterId\fR argument is
+specified, the marker is placed at the end of the display list. This
+command can be used to control how markers are displayed since markers
+are drawn in the order of this display list.
+.TP
+\fIpathName \fBmarker before \fImarkerId\fR ?\fIbeforeId\fR?
+Changes the order of the markers, drawing the first
+marker before the second. If no second \fIbeforeId\fR argument is
+specified, the marker is placed at the beginning of the display list.
+This command can be used to control how markers are displayed since
+markers are drawn in the order of this display list.
+.TP
+\fIpathName \fBmarker bind \fItagName\fR ?\fIsequence\fR? ?\fIcommand\fR?
+Associates \fIcommand\fR with \fItagName\fR such that whenever the
+event sequence given by \fIsequence\fR occurs for a marker with this
+tag, \fIcommand\fR will be invoked. The syntax is similar to the
+\fBbind\fR command except that it operates on graph markers, rather
+than widgets. See the \fBbind\fR manual entry for
+complete details on \fIsequence\fR and the substitutions performed on
+\fIcommand\fR before invoking it.
+.sp
+If all arguments are specified then a new binding is created, replacing
+any existing binding for the same \fIsequence\fR and \fItagName\fR.
+If the first character of \fIcommand\fR is \f(CW+\fR then \fIcommand\fR
+augments an existing binding rather than replacing it.
+If no \fIcommand\fR argument is provided then the command currently
+associated with \fItagName\fR and \fIsequence\fR (it's an error occurs
+if there's no such binding) is returned. If both \fIcommand\fR and
+\fIsequence\fR are missing then a list of all the event sequences for
+which bindings have been defined for \fItagName\fR.
+.TP
+\fIpathName \fBmarker cget \fIoption\fR
+Returns the current value of the marker configuration option given by
+\fIoption\fR. \fIOption\fR may be any option described
+below in the \fBconfigure\fR operation.
+.TP
+\fIpathName \fBmarker configure \fImarkerId\fR ?\fIoption value\fR?...
+Queries or modifies the configuration options for markers. If
+\fIoption\fR isn't specified, a list describing the current
+options for \fImarkerId\fR is returned. If \fIoption\fR is specified,
+but not \fIvalue\fR, then a list describing \fIoption\fR is returned.
+If one or more \fIoption\fR and \fIvalue\fR pairs are specified, then
+for each pair, the marker option \fIoption\fR is set to \fIvalue\fR.
+.sp
+The following options are valid for all markers.
+Each type of marker also has its own type-specific options.
+They are described in the sections below.
+.RS
+.TP
+\fB\-bindtags \fItagList\fR
+Specifies the binding tags for the marker. \fITagList\fR is a list
+of binding tag names. The tags and their order will determine how
+events for markers are handled. Each tag in the list matching the
+current event sequence will have its Tcl command executed. Implicitly
+the name of the marker is always the first tag in the list.
+The default value is \f(CWall\fR.
+.TP
+\fB\-coords \fIcoordList\fR
+Specifies the coordinates of the marker. \fICoordList\fR is
+a list of graph coordinates. The number of coordinates required
+is dependent on the type of marker. Text, image, and window markers
+need only two coordinates (an X\-Y coordinate). Bitmap markers
+can take either two or four coordinates (if four, they represent the
+corners of the bitmap). Line markers
+need at least four coordinates, polygons at least six.
+If \fIcoordList\fR is \f(CW""\fR, the marker will not be displayed.
+The default is \f(CW""\fR.
+.TP
+\fB\-element \fIelemName\fR
+Links the marker with the element \fIelemName\fR. The marker is
+drawn only if the element is also currently displayed (see the
+element's \fBshow\fR operation). If \fIelemName\fR is \f(CW""\fR, the
+marker is always drawn. The default is \f(CW""\fR.
+.TP
+\fB\-hide \fIboolean\fR
+Indicates whether the marker is drawn. If \fIboolean\fR is true,
+the marker is not drawn. The default is \f(CWno\fR.
+.TP
+\fB\-mapx \fIxAxis\fR
+Specifies the X\-axis to map the marker's X\-coordinates onto.
+\fIXAxis\fR must the name of an axis. The default is \f(CWx\fR.
+.TP
+\fB\-mapy \fIyAxis\fR
+Specifies the Y\-axis to map the marker's Y\-coordinates onto.
+\fIYAxis\fR must the name of an axis. The default is \f(CWy\fR.
+.TP
+\fB\-name \fImarkerId\fR
+Changes the identifier for the marker. The identifier \fImarkerId\fR
+can not already be used by another marker. If this option
+isn't specified, the marker's name is uniquely generated.
+.TP
+\fB\-under \fIboolean\fR
+Indicates whether the marker is drawn below/above data
+elements. If \fIboolean\fR is true, the marker is be drawn
+underneath the data element symbols and lines. Otherwise, the marker is
+drawn on top of the element. The default is \f(CW0\fR.
+.TP
+\fB\-xoffset \fIpixels\fR
+Specifies a screen distance to offset the marker horizontally.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+The default is \f(CW0\fR.
+.TP
+\fB\-yoffset \fIpixels\fR
+Specifies a screen distance to offset the markers vertically.
+\fIPixels\fR is a valid screen distance, such as \f(CW2\fR or \f(CW1.2i\fR.
+The default is \f(CW0\fR.
+.PP
+Marker configuration options may also be set by the \fBoption\fR command.
+The resource class is either \f(CWBitmapMarker\fR, \f(CWImageMarker\fR,
+\f(CWLineMarker\fR, \f(CWPolygonMarker\fR, \f(CWTextMarker\fR, or \f(CWWindowMarker\fR,
+depending on the type of marker. The resource name is the name of the
+marker.
+.CS
+option add *Graph.TextMarker.Foreground white
+option add *Graph.BitmapMarker.Foreground white
+option add *Graph.m1.Background blue
+.CE
+.RE
+.TP
+\fIpathName \fBmarker create \fItype\fR ?\fIoption value\fR?...
+Creates a marker of the selected type. \fIType\fR may be either
+\f(CWtext\fR, \f(CWline\fR, \f(CWbitmap\fR, \f(CWimage\fR, \f(CWpolygon\fR, or
+\f(CWwindow\fR. This command returns the marker identifier,
+used as the \fImarkerId\fR argument in the other marker-related
+commands. If the \fB\-name\fR option is used, this overrides the
+normal marker identifier. If the name provided is already used for
+another marker, the new marker will replace the old.
+.TP
+\fIpathName \fBmarker delete\fR ?\fIname\fR?...
+Removes one of more markers. The graph will automatically be redrawn
+without the marker.\fR.
+.TP
+\fIpathName \fBmarker exists \fImarkerId\fR
+Returns \f(CW1\fR if the marker \fImarkerId\fR exists and \f(CW0\fR
+otherwise.
+.TP
+\fIpathName \fBmarker names\fR ?\fIpattern\fR?
+Returns the names of all the markers that currently exist. If
+\fIpattern\fR is supplied, only those markers whose names match it
+will be returned.
+.TP
+\fIpathName \fBmarker type \fImarkerId\fR
+Returns the type of the marker given by \fImarkerId\fR, such as
+\f(CWline\fR or \f(CWtext\fR. If \fImarkerId\fR is not a valid a marker
+identifier, \f(CW""\fR is returned.
+.SS "BITMAP MARKERS"
+A bitmap marker displays a bitmap. The size of the
+bitmap is controlled by the number of coordinates specified. If two
+coordinates, they specify the position of the top-left corner of the
+bitmap. The bitmap retains its normal width and height. If four
+coordinates, the first and second pairs of coordinates represent the
+corners of the bitmap. The bitmap will be stretched or reduced as
+necessary to fit into the bounding rectangle.
+.PP
+Bitmap markers are created with the marker's \fBcreate\fR operation in
+the form:
+.DS
+\fIpathName \fBmarker create bitmap \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR pairs, each
+sets a configuration options for the marker. These
+same \fIoption\fR\-\fIvalue\fR pairs may be used with the marker's
+\fBconfigure\fR operation.
+.PP
+The following options are specific to bitmap markers:
+.TP
+\fB\-background \fIcolor\fR
+Same as the \fB\-fill\fR option.
+.TP
+\fB\-bitmap \fIbitmap\fR
+Specifies the bitmap to be displayed. If \fIbitmap\fR is \f(CW""\fR,
+the marker will not be displayed. The default is \f(CW""\fR.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the bitmap. If \fIcolor\fR is the empty
+string, no background will be transparent. The default background color is
+\f(CW""\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Same as the \fB\-outline\fR option.
+.TP
+\fB\-mask \fImask\fR
+Specifies a mask for the bitmap to be displayed. This mask is a bitmap
+itself, denoting the pixels that are transparent. If \fImask\fR is
+\f(CW""\fR, all pixels of the bitmap will be drawn. The default is
+\f(CW""\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the foreground color of the bitmap. The default value is \f(CWblack\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Sets the rotation of the bitmap. \fITheta\fR is a real number
+representing the angle of rotation in degrees. The marker is first
+rotated and then placed according to its anchor position. The default
+rotation is \f(CW0.0\fR.
+.SS "IMAGE MARKERS"
+A image marker displays an image. Image markers are
+created with the marker's \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create image \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to image markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the image relative to the
+positioning point for the image. For example, if \fIanchor\fR
+is \f(CWcenter\fR then the image is centered on the point; if
+\fIanchor\fR is \f(CWn\fR then the image will be drawn such that
+the top center point of the rectangular region occupied by the
+image will be at the positioning point.
+This option defaults to \f(CWcenter\fR.
+.TP
+\fB\-image \fIimage\fR
+Specifies the image to be drawn.
+If \fIimage\fR is \f(CW""\fR, the marker will not be
+drawn. The default is \f(CW""\fR.
+.SS "LINE MARKERS"
+A line marker displays one or more connected line segments.
+Line markers are created with marker's \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create line \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to line markers:
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the line. \fIDashList\fR is a list of up to 11
+numbers that alternately represent the lengths of the dashes and gaps
+on the line. Each number must be between 1 and 255. If
+\fIdashList\fR is \f(CW""\fR, the marker line will be solid.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the line. This color is used with
+striped lines (see the \fB\-fdashes\fR option). If \fIcolor\fR is
+the empty string, no background color is drawn (the line will be
+dashed, not striped). The default background color is \f(CW""\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the lines.
+The default width is \f(CW0\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the foreground color of the line. The default value is \f(CWblack\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies a stipple pattern used to draw the line, rather than
+a solid line.
+\fIBitmap\fR specifies a bitmap to use as the stipple
+pattern. If \fIbitmap\fR is \f(CW""\fR, then the
+line is drawn in a solid fashion. The default is \f(CW""\fR.
+.SS "POLYGON MARKERS"
+A polygon marker displays a closed region described as two or more
+connected line segments. It is assumed the first and
+last points are connected. Polygon markers are created using the
+marker \fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create polygon \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the \fBmarker configure\fR command to change the marker's
+configuration.
+The following options are supported for polygon markers:
+.TP
+\fB\-dashes \fIdashList\fR
+Sets the dash style of the outline of the polygon. \fIDashList\fR is a
+list of up to 11 numbers that alternately represent the lengths of
+the dashes and gaps on the outline. Each number must be between 1 and
+255. If \fIdashList\fR is \f(CW""\fR, the outline will be a solid line.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the fill color of the polygon. If \fIcolor\fR is \f(CW""\fR, then
+the interior of the polygon is transparent.
+The default is \f(CWwhite\fR.
+.TP
+\fB\-linewidth \fIpixels\fR
+Sets the width of the outline of the polygon. If \fIpixels\fR is zero,
+no outline is drawn. The default is \f(CW0\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color of the outline of the polygon. If the polygon is
+stippled (see the \fB\-stipple\fR option), then this represents the
+foreground color of the stipple. The default is \f(CWblack\fR.
+.TP
+\fB\-stipple \fIbitmap\fR
+Specifies that the polygon should be drawn with a stippled pattern
+rather than a solid color. \fIBitmap\fR specifies a bitmap to use as
+the stipple pattern. If \fIbitmap\fR is \f(CW""\fR, then the polygon is
+filled with a solid color (if the \fB\-fill\fR option is set). The
+default is \f(CW""\fR.
+.SS "TEXT MARKERS"
+A text marker displays a string of characters on one or more lines of
+text. Embedded newlines cause line breaks. They may be used to
+annotate regions of the graph. Text markers are created with the
+\fBcreate\fR operation in the form:
+.DS
+\fIpathName \fBmarker create text \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR pairs,
+each sets a configuration option for the text marker.
+These same \fIoption\fR\-\fIvalue\fR pairs may be used with the
+marker's \fBconfigure\fR operation.
+.PP
+The following options are specific to text markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the text relative to the
+positioning point for the text. For example, if \fIanchor\fR is
+\f(CWcenter\fR then the text is centered on the point; if
+\fIanchor\fR is \f(CWn\fR then the text will be drawn such that the
+top center point of the rectangular region occupied by the text will
+be at the positioning point. This default is \f(CWcenter\fR.
+.TP
+\fB\-background \fIcolor\fR
+Same as the \fB\-fill\fR option.
+.TP
+\fB\-font \fIfontName\fR
+Specifies the font of the text. The default is
+\f(CW*-Helvetica-Bold-R-Normal-*-120-*\fR.
+.TP
+\fB\-fill \fIcolor\fR
+Sets the background color of the text. If \fIcolor\fR is the empty
+string, no background will be transparent. The default background color is
+\f(CW""\fR.
+.TP
+\fB\-foreground \fIcolor\fR
+Same as the \fB\-outline\fR option.
+.TP
+\fB\-justify \fIjustify\fR
+Specifies how the text should be justified. This matters only when
+the marker contains more than one line of text. \fIJustify\fR must be
+\f(CWleft\fR, \f(CWright\fR, or \f(CWcenter\fR. The default is
+\f(CWcenter\fR.
+.TP
+\fB\-outline \fIcolor\fR
+Sets the color of the text. The default value is \f(CWblack\fR.
+.TP
+\fB\-padx \fIpad\fR
+Sets the padding to the left and right exteriors of the text.
+\fIPad\fR can be a list of one or two screen distances. If \fIpad\fR
+has two elements, the left side of the text is padded by the first
+distance and the right side by the second. If \fIpad\fR has just one
+distance, both the left and right sides are padded evenly. The
+default is \f(CW4\fR.
+.TP
+\fB\-pady \fIpad\fR
+Sets the padding above and below the text. \fIPad\fR can be a list of
+one or two screen distances. If \fIpad\fR has two elements, the area above the
+text is padded by the first distance and the area below by the second.
+If \fIpad\fR is just one distance, both the top and bottom areas
+are padded evenly. The default is \f(CW4\fR.
+.TP
+\fB\-rotate \fItheta\fR
+Specifies the number of degrees to rotate the text. \fITheta\fR is a
+real number representing the angle of rotation. The marker is first
+rotated along its center and is then drawn according to its anchor
+position. The default is \f(CW0.0\fR.
+.TP
+\fB\-text \fItext\fR
+Specifies the text of the marker. The exact way the text is
+displayed may be affected by other options such as \fB\-anchor\fR or
+\fB\-rotate\fR.
+.SS "WINDOW MARKERS"
+A window marker displays a widget at a given position.
+Window markers are created with the marker's \fBcreate\fR operation in
+the form:
+.DS
+\fIpathName \fBmarker create window \fR?\fIoption value\fR?...
+.DE
+There may be many \fIoption\fR-\fIvalue\fR
+pairs, each sets a configuration option
+for the marker. These same \fIoption\fR\-\fIvalue\fR pairs may be
+used with the marker's \fBconfigure\fR command.
+.PP
+The following options are specific to window markers:
+.TP
+\fB\-anchor \fIanchor\fR
+\fIAnchor\fR tells how to position the widget relative to the
+positioning point for the widget. For example, if \fIanchor\fR is
+\f(CWcenter\fR then the widget is centered on the point; if \fIanchor\fR
+is \f(CWn\fR then the widget will be displayed such that the top center
+point of the rectangular region occupied by the widget will be at the
+positioning point. This option defaults to \f(CWcenter\fR.
+.TP
+\fB\-height \fIpixels\fR
+Specifies the height to assign to the marker's window. If this option
+isn't specified, or if it is specified as \f(CW""\fR, then the window is
+given whatever height the widget requests internally.
+.TP
+\fB\-width \fIpixels\fR
+Specifies the width to assign to the marker's window. If this option
+isn't specified, or if it is specified as \f(CW""\fR, then the window is
+given whatever width the widget requests internally.
+.TP
+\fB\-window \fIpathName\fR
+Specifies the widget to be managed by the graph. \fIPathName\fR must
+be a child of the \fBgraph\fR widget.
+.SH "GRAPH COMPONENT BINDINGS"
+Specific graph components, such as elements, markers and legend
+entries, can have a command trigger when event occurs in them, much
+like canvas items in Tk's canvas widget. Not all event sequences are
+valid. The only binding events that may be specified are those
+related to the mouse and keyboard (such as \fBEnter\fR, \fBLeave\fR,
+\fBButtonPress\fR, \fBMotion\fR, and \fBKeyPress\fR).
+.PP
+Only one element or marker can be picked during an event. This means,
+that if the mouse is directly over both an element and a marker, only
+the uppermost component is selected. This isn't true for legend entries.
+Both a legend entry and an element (or marker) binding commands
+will be invoked if both items are picked.
+.PP
+It is possible for multiple bindings to match a particular event.
+This could occur, for example, if one binding is associated with the
+element name and another is associated with one of the element's tags
+(see the \fB\-bindtags\fR option). When this occurs, all of the
+matching bindings are invoked. A binding associated with the element
+name is invoked first, followed by one binding for each of the element's
+bindtags. If there are multiple matching bindings for a single tag,
+then only the most specific binding is invoked. A continue command
+in a binding script terminates that script, and a break command
+terminates that script and skips any remaining scripts for the event,
+just as for the bind command.
+.PP
+The \fB\-bindtags\fR option for these components controls addition
+tag names which can be matched. Implicitly elements and markers
+always have tags matching their names. Setting the value of
+the \fB\-bindtags\fR option doesn't change this.
+.SH "C LANGUAGE API"
+You can manipulate data elements from the C language. There
+may be situations where it is too expensive to translate the data
+values from ASCII strings. Or you might want to read data in a
+special file format.
+.PP
+Data can manipulated from the C language using BLT vectors.
+You specify the X-Y data coordinates of an element as vectors and
+manipulate the vector from C. The graph will be redrawn automatically
+after the vectors are updated.
+.PP
+From Tcl, create the vectors and configure the element to use them.
+.CS
+vector X Y
+\&.g element configure line1 -xdata X -ydata Y
+.CE
+To set data points from C, you pass the values as arrays of doubles
+using the \fBBlt_ResetVector\fR call. The vector is reset with the
+new data and at the next idle point (when Tk re-enters its event
+loop), the graph will be redrawn automatically.
+.CS
+#include <tcl.h>
+#include <blt.h>
+
+register int i;
+Blt_Vector *xVec, *yVec;
+double x[50], y[50];
+
+/* Get the BLT vectors "X" and "Y" (created above from Tcl) */
+if ((Blt_GetVector(interp, "X", &xVec) != TCL_OK) ||
+ (Blt_GetVector(interp, "Y", &yVec) != TCL_OK)) {
+ return TCL_ERROR;
+}
+
+for (i = 0; i < 50; i++) {
+ x[i] = i * 0.02;
+ y[i] = sin(x[i]);
+}
+
+/* Put the data into BLT vectors */
+if ((Blt_ResetVector(xVec, x, 50, 50, TCL_VOLATILE) != TCL_OK) ||
+ (Blt_ResetVector(yVec, y, 50, 50, TCL_VOLATILE) != TCL_OK)) {
+ return TCL_ERROR;
+}
+.CE
+See the \fBvector\fR manual page for more details.
+.SH SPEED TIPS
+There may be cases where the graph needs to be drawn and updated as
+quickly as possible. If drawing speed becomes a big
+problem, here are a few tips to speed up displays.
+.TP 2
+\(bu
+Try to minimize the number of data points. The more data points
+the looked at, the more work the graph must do.
+.TP 2
+\(bu
+If your data is generated as floating point values, the time required
+to convert the data values to and from ASCII strings can be
+significant, especially when there any many data points. You can
+avoid the redundant string-to-decimal conversions using the C API to
+BLT vectors.
+.TP 2
+\(bu
+Data elements without symbols are drawn faster than with symbols.
+Set the data element's \fB\-symbol\fR option to \f(CWnone\fR. If you need to
+draw symbols, try using the simple symbols such as \f(CWsplus\fR and
+\f(CWscross\fR.
+.TP 2
+\(bu
+Don't stipple or dash the element. Solid lines are much faster.
+.TP 2
+\(bu
+If you update data elements frequently, try turning off the
+widget's \fB\-bufferelements\fR option. When the graph is first
+displayed, it draws data elements into an internal pixmap. The pixmap
+acts as a cache, so that when the graph needs to be redrawn again, and
+the data elements or coordinate axes haven't changed, the pixmap is
+simply copied to the screen. This is especially useful when you are
+using markers to highlight points and regions on the graph. But if
+the graph is updated frequently, changing either the element data or
+coordinate axes, the buffering becomes redundant.
+.SH LIMITATIONS
+Auto-scale routines do not use requested min/max limits as boundaries
+when the axis is logarithmically scaled.
+.PP
+The PostScript output generated for polygons with more than 1500
+points may exceed the limits of some printers (See PostScript Language
+Reference Manual, page 568). The work-around is to break the polygon
+into separate pieces.
+.SH KEYWORDS
+graph, widget
diff --git a/tlt3.0/doc/vector.n b/tlt3.0/doc/vector.n
new file mode 100644
index 0000000..da7abf2
--- /dev/null
+++ b/tlt3.0/doc/vector.n
@@ -0,0 +1,1130 @@
+'\"
+'\" Copyright 1991-1997 by Lucent Technologies, Inc.
+'\"
+'\" 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 the
+'\" copyright notice and warranty disclaimer appear in supporting documentation,
+'\" and that the names of Lucent Technologies any of their entities not be used
+'\" in advertising or publicity pertaining to distribution of the software
+'\" without specific, written prior permission.
+'\"
+'\" Lucent Technologies disclaims all warranties with regard to this software,
+'\" including all implied warranties of merchantability and fitness. In no event
+'\" shall Lucent Technologies 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
+'\" tortuous action, arising out of or in connection with the use or performance
+'\" of this software.
+'\"
+'\" Vector command created by George Howlett.
+'\"
+.so man.macros
+.TH blt::vector n BLT_VERSION BLT "BLT Built-In Commands"
+.BS
+'\" Note: do not modify the .SH NAME line immediately below!
+.SH NAME
+\fBvector\fR \- Vector data type for Tcl
+.SH SYNOPSIS
+\fBblt::vector create \fIvecName \fR?\fIvecName\fR...? ?\fIswitches\fR?
+.sp
+\fBblt::vector destroy \fIvecName \fR?\fIvecName\fR...?
+.sp
+\fBblt::vector expr \fIexpression\fR
+.sp
+\fBblt::vector names \fR?\fIpattern\fR...?
+.BE
+.SH DESCRIPTION
+The \fBvector\fR command creates an array of floating point
+values. The vector's components can be manipulated in three ways:
+through a Tcl array variable, a Tcl command, or the C API.
+.SH INTRODUCTION
+A vector is an ordered set of real numbers. The components of a
+vector are indexed by integers.
+.PP
+Vectors are common data structures for many applications. For
+example, a graph may use two vectors to represent the X-Y
+coordinates of the data plotted. The graph will automatically
+be redrawn when the vectors are updated or changed. By using vectors,
+you can separate
+data analysis from the graph widget. This makes it easier, for
+example, to add data transformations, such as splines. It's possible
+to plot the same data to in multiple graphs, where each graph presents
+a different view or scale of the data.
+.PP
+You could try to use Tcl's associative arrays as vectors. Tcl arrays
+are easy to use. You can access individual elements randomly by
+specifying the index, or the set the entire array by providing a list
+of index and value pairs for each element. The disadvantages of
+associative arrays as vectors lie in the fact they are implemented as
+hash tables.
+.TP 2
+\(bu
+There's no implied ordering to the associative arrays. If you used
+vectors for plotting, you would want to insure the second component
+comes after the first, an so on. This isn't possible since arrays
+are actually hash tables. For example, you can't get a range of
+values between two indices. Nor can you sort an array.
+.TP 2
+\(bu
+Arrays consume lots of memory when the number of elements becomes
+large (tens of thousands). This is because each element's index and
+value are stored as strings in the hash table.
+.TP 2
+\(bu
+The C programming interface is unwieldy. Normally with vectors, you
+would like to view the Tcl array as you do a C array, as an array of
+floats or doubles. But with hash tables, you must convert both the
+index and value to and from decimal strings, just to access
+an element in the array. This makes it cumbersome to perform operations on
+the array as a whole.
+.PP
+The \fBvector\fR command tries to overcome these disadvantages while
+still retaining the ease of use of Tcl arrays. The \fBvector\fR
+command creates both a new Tcl command and associate array which are
+linked to the vector components. You can randomly access vector
+components though the elements of array. Not have all indices are
+generated for the array, so printing the array (using the \fBparray\fR
+procedure) does not print out all the component values. You can use
+the Tcl command to access the array as a whole. You can copy, append,
+or sort vector using its command. If you need greater performance, or
+customized behavior, you can write your own C code to manage vectors.
+.SH EXAMPLE
+You create vectors using the \fBvector\fR command and its \fBcreate\fR
+operation.
+.CS
+# Create a new vector.
+blt::vector create y(50)
+.CE
+This creates a new vector named \f(CWy\fR. It has fifty components, by
+default, initialized to \f(CW0.0\fR. In addition, both a Tcl command
+and array variable, both named \f(CWy\fR, are created. You can use
+either the command or variable to query or modify components of the
+vector.
+.CS
+# Set the first value.
+set y(0) 9.25
+puts "y has [y length] components"
+.CE
+The array \f(CWy\fR can be used to read or set individual components of
+the vector. Vector components are indexed from zero. The array index
+must be a number less than the number of components. For example,
+it's an error if you try to set the 51st element of \f(CWy\fR.
+.CS
+# This is an error. The vector only has 50 components.
+set y(50) 0.02
+.CE
+You can also specify a range of indices using a colon (:) to separate
+the first and last indices of the range.
+.CS
+# Set the first six components of y
+set y(0:5) 25.2
+.CE
+If you don't include an index, then it will default to the first
+and/or last component of the vector.
+.CS
+# Print out all the components of y
+puts "y = $y(:)"
+.CE
+There are special non-numeric indices. The index \f(CWend\fR, specifies
+the last component of the vector. It's an error to use this index if
+the vector is empty (length is zero). The index \f(CW++end\fR can be
+used to extend the vector by one component and initialize it to a specific
+value. You can't read from the array using this index, though.
+.CS
+# Extend the vector by one component.
+set y(++end) 0.02
+.CE
+The other special indices are \f(CWmin\fR and \f(CWmax\fR. They return the
+current smallest and largest components of the vector.
+.CS
+# Print the bounds of the vector
+puts "min=$y(min) max=$y(max)"
+.CE
+To delete components from a vector, simply unset the corresponding
+array element. In the following example, the first component of
+\f(CWy\fR is deleted. All the remaining components of \f(CWy\fR will be
+moved down by one index as the length of the vector is reduced by
+one.
+.CS
+# Delete the first component
+unset y(0)
+puts "new first element is $y(0)"
+.CE
+The vector's Tcl command can also be used to query or set the vector.
+.CS
+# Create and set the components of a new vector
+blt::vector create x
+x set { 0.02 0.04 0.06 0.08 0.10 0.12 0.14 0.16 0.18 0.20 }
+.CE
+Here we've created a vector \f(CWx\fR without a initial length specification.
+In this case, the length is zero. The \fBset\fR operation resets the vector,
+extending it and setting values for each new component.
+.PP
+There are several operations for vectors. The \fBrange\fR operation
+lists the components of a vector between two indices.
+.CS
+# List the components
+puts "x = [x range 0 end]"
+.CE
+You can search for a particular value using the \fBsearch\fR
+operation. It returns a list of indices of the components with the
+same value. If no component has the same value, it returns \f(CW""\fR.
+.CS
+# Find the index of the biggest component
+set indices [x search $x(max)]
+.CE
+Other operations copy, append, or sort vectors. You can append
+vectors or new values onto an existing vector with the \fBappend\fR
+operation.
+.CS
+# Append assorted vectors and values to x
+x append x2 x3 { 2.3 4.5 } x4
+.CE
+The \fBsort\fR operation sorts the vector. If any additional vectors
+are specified, they are rearranged in the same order as the vector.
+For example, you could use it to sort data points represented by x and
+y vectors.
+.CS
+# Sort the data points
+x sort y
+.CE
+The vector \f(CWx\fR is sorted while the components of \f(CWy\fR are
+rearranged so that the original x,y coordinate pairs are retained.
+.PP
+The \fBexpr\fR operation lets you perform arithmetic on vectors.
+The result is stored in the vector.
+.CS
+# Add the two vectors and a scalar
+x expr { x + y }
+x expr { x * 2 }
+.CE
+When a vector is modified, resized, or deleted, it may trigger
+call-backs to notify the clients of the vector. For example, when a
+vector used in the \fBgraph\fR widget is updated, the vector
+automatically notifies the widget that it has changed. The graph can
+then redrawn itself at the next idle point. By default, the
+notification occurs when Tk is next idle. This way you can modify the
+vector many times without incurring the penalty of the graph redrawing
+itself for each change. You can change this behavior using the
+\fBnotify\fR operation.
+.CS
+# Make vector x notify after every change
+x notify always
+ ...
+# Never notify
+x notify never
+ ...
+# Force notification now
+x notify now
+.CE
+To delete a vector, use the \fBvector delete\fR command.
+Both the vector and its corresponding Tcl command are destroyed.
+.CS
+# Remove vector x
+blt::vector destroy x
+.CE
+.SH SYNTAX
+Vectors are created using the \fBvector create\fR operation.
+Th \fBcreate\fR operation can be invoked in one of three forms:
+.TP
+\fBblt::vector create \fIvecName\fR
+This creates a new vector \fIvecName\fR which initially has no components.
+.TP
+\fBblt::vector create \fIvecName\fR(\fIsize\fR)
+This second form creates a new vector which will contain \fIsize\fR
+number of components. The components will be indexed starting from
+zero (0). The default value for the components is \f(CW0.0\fR.
+.TP
+\fBblt::vector create \fIvecName\fR(\fIfirst\fR:\fIlast\fR)
+The last form creates a new vector of indexed \fIfirst\fR through
+\fIlast\fR. \fIFirst\fR and \fIlast\fR can be any integer value
+so long as \fIfirst\fR is less than \fIlast\fR.
+.PP
+Vector names must start with a letter and consist of letters, digits,
+or underscores.
+.CS
+# Error: must start with letter
+blt::vector create 1abc
+.CE
+You can automatically generate vector names using the
+"\f(CW#auto\fR" vector name. The \fBcreate\fR operation will generate a
+unique vector name.
+.CS
+set vec [blt::vector create #auto]
+puts "$vec has [$vec length] components"
+.CE
+.SS VECTOR INDICES
+Vectors are indexed by integers. You can access the individual vector
+components via its array variable or Tcl command. The string
+representing the index can be an integer, a numeric expression, a
+range, or a special keyword.
+.PP
+The index must lie within the current range of the vector, otherwise
+an an error message is returned. Normally the indices of a vector
+are start from 0. But you can use the \fBoffset\fR operation to
+change a vector's indices on-the-fly.
+.CS
+puts $vecName(0)
+vecName offset -5
+puts $vecName(-5)
+.CE
+You can also use numeric expressions as indices. The result
+of the expression must be an integer value.
+.CS
+set n 21
+set vecName($n+3) 50.2
+.CE
+The following special non-numeric indices are available: \f(CWmin\fR, \f(CWmax\fR, \f(CWend\fR, and
+\f(CW++end\fR.
+.CS
+puts "min = $vecName($min)"
+set vecName(end) -1.2
+.CE
+The indices \f(CWmin\fR and \f(CWmax\fR will return the minimum and maximum
+values of the vector. The index \f(CWend\fR returns the value of the
+last component in the vector. The index \f(CW++end\fR is used to append
+new value onto the vector. It automatically extends the vector by
+one component and sets its value.
+.CS
+# Append an new component to the end
+set vecName(++end) 3.2
+.CE
+A range of indices can be indicated by a colon (:).
+.CS
+# Set the first six components to 1.0
+set vecName(0:5) 1.0
+.CE
+If no index is supplied the first or last component is assumed.
+.CS
+# Print the values of all the components
+puts $vecName(:)
+.CE
+.SH VECTOR OPERATIONS
+.TP
+\fBblt::vector create \fIvecName\fR?(\fIsize\fR)?... \fR?\fIswitches\fR?
+The \fBcreate\fR operation creates a new vector \fIvecName\fR. Both a
+Tcl command and array variable \fIvecName\fR are also created. The
+name \fIvecName\fR must be unique, so another Tcl command or array
+variable can not already exist in that scope. You can access the
+components of the vector using its variable. If you change a value in
+the array, or unset an array element, the vector is updated to reflect
+the changes. When the variable \fIvecName\fR is unset, the vector and
+its Tcl command are also destroyed.
+.sp
+The vector has optional switches that affect how the vector is created. They
+are as follows:
+.RS
+.TP
+\fB\-variable \fIvarName\fR
+Specifies the name of a Tcl variable to be mapped to the vector. If
+the variable already exists, it is first deleted, then recreated.
+If \fIvarName\fR is the empty string, then no variable will be mapped.
+You can always map a variable back to the vector using the vector's
+\fBvariable\fR operation.
+.TP
+\fB\-command \fIcmdName\fR
+Maps a Tcl command to the vector. The vector can be accessed using
+\fIcmdName\fR and one of the vector instance operations.
+A Tcl command by that name cannot already exist.
+If \fIcmdName\fR is the empty string, no command mapping
+will be made.
+.TP
+\fB\-watchunset \fIboolean\fR
+Indicates that the vector should automatically delete itself if
+the variable associated with the vector is unset. By default,
+the vector will not be deleted. This is different from previous
+releases. Set \fIboolean\fR to "true" to get the old behavior.
+.RE
+.TP
+\fBblt::vector destroy \fIvecName\fR \fR?\fIvecName...\fR?
+Deletes one or more vectors. Both the Tcl command and array variable
+are removed also.
+.TP
+\fBblt::vector expr \fIexpression\fR
+.RS
+All binary operators take vectors as operands (remember that numbers
+are treated as one-component vectors). The exact action of binary
+operators depends upon the length of the second operand. If the
+second operand has only one component, then each element of the first
+vector operand is computed by that value. For example, the expression
+"x * 2" multiples all elements of the vector x by 2. If the second
+operand has more than one component, both operands must be the same
+length. Each pair of corresponding elements are computed. So "x + y"
+adds the the first components of x and y together, the second, and so on.
+.sp
+The valid operators are listed below, grouped in decreasing order
+of precedence:
+.TP 20
+\fB\-\0\0!\fR
+Unary minus and logical NOT. The unary minus flips the sign of each
+component in the vector. The logical not operator returns a vector of
+whose values are 0.0 or 1.0. For each non-zero component 1.0 is returned,
+0.0 otherwise.
+.TP 20
+\fB^\fR
+Exponentiation.
+.TP 20
+\fB*\0\0/\0\0%\fR
+Multiply, divide, remainder.
+.TP 20
+\fB+\0\0\-\fR
+Add and subtract.
+.TP 20
+\fB<<\0\0>>\fR
+Left and right shift. Circularly shifts the values of the vector
+(not implemented yet).
+.TP 20
+\fB<\0\0>\0\0<=\0\0>=\fR
+Boolean less, greater, less than or equal, and greater than or equal.
+Each operator returns a vector of ones and zeros. If the condition is true,
+1.0 is the component value, 0.0 otherwise.
+.TP 20
+\fB==\0\0!=\fR
+Boolean equal and not equal.
+Each operator returns a vector of ones and zeros. If the condition is true,
+1.0 is the component value, 0.0 otherwise.
+.TP 20
+\fB|\fR
+Bit-wise OR. (Not implemented).
+.TP 20
+\fB&&\fR
+Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise.
+.TP 20
+\fB||\fR
+Logical OR. Produces a 0 result if both operands are zero, 1 otherwise.
+.TP 20
+\fIx\fB?\fIy\fB:\fIz\fR
+If-then-else, as in C. (Not implemented yet).
+.LP
+See the C manual for more details on the results produced by each
+operator. All of the binary operators group left-to-right within the
+same precedence level.
+.sp
+Several mathematical functions are supported for vectors. Each of
+the following functions invokes the math library function of the same name;
+see the manual entries for the library functions for details on what
+they do. The operation is applied to all elements of the vector
+returning the results.
+.CS
+.ta 3c 6c 9c
+\fBacos\fR \fBcos\fR \fBhypot\fR \fBsinh\fR
+\fBasin\fR \fBcosh\fR \fBlog\fR \fBsqrt\fR
+\fBatan\fR \fBexp\fR \fBlog10\fR \fBtan\fR
+\fBceil\fR \fBfloor\fR \fBsin\fR \fBtanh\fR
+.CE
+Additional functions are:
+.TP 1i
+\fBabs\fR
+Returns the absolute value of each component.
+.TP 1i
+\fBrandom\fR
+Returns a vector of non-negative values uniformly distributed
+between [0.0, 1.0) using \fIdrand48\fR.
+The seed comes from the internal clock of the machine or may be
+set manual with the srandom function.
+.TP 1i
+\fBround\fR
+Rounds each component of the vector.
+.TP 1i
+\fBsrandom\fR
+Initializes the random number generator using \fIsrand48\fR.
+The high order 32-bits are set using the integral portion of the first
+vector component. All other components are ignored. The low order 16-bits
+are set to an arbitrary value.
+.PP
+The following functions return a single value.
+.TP 1i
+\fBadev\fR
+Returns the average deviation (defined as the sum of the absolute values
+of the differences between component and the mean, divided by the length
+of the vector).
+.TP 1i
+\fBkurtosis\fR
+Returns the degree of peakedness (fourth moment) of the vector.
+.TP 1i
+\fBlength\fR
+Returns the number of components in the vector.
+.TP 1i
+\fBmax\fR
+Returns the vector's maximum value.
+.TP 1i
+\fBmean\fR
+Returns the mean value of the vector.
+.TP 1i
+\fBmedian\fR
+Returns the median of the vector.
+.TP 1i
+\fBmin\fR
+Returns the vector's minimum value.
+.TP 1i
+\fBq1\fR
+Returns the first quartile of the vector.
+.TP 1i
+\fBq3\fR
+Returns the third quartile of the vector.
+.TP 1i
+\fBprod\fR
+Returns the product of the components.
+.TP 1i
+\fBsdev\fR
+Returns the standard deviation (defined as the square root of the variance)
+of the vector.
+.TP 1i
+\fBskew\fR
+Returns the skewness (or third moment) of the vector. This characterizes
+the degree of asymmetry of the vector about the mean.
+.TP 1i
+\fBsum\fR
+Returns the sum of the components.
+.TP 1i
+\fBvar\fR
+Returns the variance of the vector. The sum of the squared differences
+between each component and the mean is computed. The variance is
+the sum divided by the length of the vector minus 1.
+.PP
+The last set returns a vector of the same length as the argument.
+.TP 1i
+\fBnorm\fR
+Scales the values of the vector to lie in the range [0.0..1.0].
+.TP 1i
+\fBsort\fR
+Returns the vector components sorted in ascending order.
+.RE
+.TP
+\fBvector names \fR?\fIpattern\fR?
+.SH INSTANCE OPERATIONS
+You can also use the vector's Tcl command to query or modify it. The
+general form is
+.DS
+\fIvecName \fIoperation\fR \fR?\fIarg\fR?...
+.DE
+Both \fIoperation\fR and its arguments determine the exact behavior of
+the command. The operations available for vectors are listed below.
+.TP
+\fIvecName \fBappend\fR \fIitem\fR ?\fIitem\fR?...
+Appends the component values from \fIitem\fR to \fIvecName\fR.
+\fIItem\fR can be either the name of a vector or a list of numeric
+values.
+.TP
+\fIvecName \fBbinread\fR \fIchannel\fR ?\fIlength\fR? ?\fIswitches\fR?
+Reads binary values from a Tcl channel. Values are either appended
+to the end of the vector or placed at a given index (using the
+\fB\-at\fR option), overwriting existing values. Data is read until EOF
+is found on the channel or a specified number of values \fIlength\fR
+are read (note that this is not necessarily the same as the number of
+bytes). The following switches are supported:
+.RS
+.TP
+\fB\-swap\fR
+Swap bytes and words. The default endian is the host machine.
+.TP
+\fB\-at \fIindex\fR
+New values will start at vector index \fIindex\fR. This will
+overwrite any current values.
+.TP
+\fB\-format\fR \fIformat\fR
+Specifies the format of the data. \fIFormat\fR can be one of the
+following: "i1", "i2", "i4", "i8", "u1, "u2", "u4", "u8", "r4",
+"r8", or "r16". The number indicates the number of bytes
+required for each value. The letter indicates the type: "i" for signed,
+"u" for unsigned, "r" or real. The default format is "r16".
+.RE
+.TP
+\fIvecName \fBclear\fR
+Clears the element indices from the array variable associated with
+\fIvecName\fR. This doesn't affect the components of the vector. By
+default, the number of entries in the Tcl array doesn't match the
+number of components in the vector. This is because its too expensive
+to maintain decimal strings for both the index and value for each
+component. Instead, the index and value are saved only when you read
+or write an element with a new index. This command removes the index
+and value strings from the array. This is useful when the vector is
+large.
+.TP
+\fIvecName \fBdelete\fR \fIindex\fR ?\fIindex\fR?...
+Deletes the \fIindex\fRth component from the vector \fIvecName\fR.
+\fIIndex\fR is the index of the element to be deleted. This is the
+same as unsetting the array variable element \fIindex\fR. The vector
+is compacted after all the indices have been deleted.
+.TP
+\fIvecName \fBdup\fR \fIdestName\fR
+Copies \fIvecName\fR to \fIdestName\fR. \fIDestName\fR is the name of a
+destination vector. If a vector \fIdestName\fR already exists, it is
+overwritten with the components of \fIvecName\fR. Otherwise a
+new vector is created.
+.TP
+\fIvecName \fBexpr\fR \fIexpression\fR
+Computes the expression and resets the values of the vector accordingly.
+Both scalar and vector math operations are allowed. All values in
+expressions are either real numbers or names of vectors. All numbers
+are treated as one component vectors.
+.TP
+\fIvecName \fBlength\fR ?\fInewSize\fR?
+Queries or resets the number of components in \fIvecName\fR.
+\fINewSize\fR is a number specifying the new size of the vector. If
+\fInewSize\fR is smaller than the current size of \fIvecName\fR,
+\fIvecName\fR is truncated. If \fInewSize\fR is greater, the vector
+is extended and the new components are initialized to \f(CW0.0\fR. If
+no \fInewSize\fR argument is present, the current length of the vector
+is returned.
+.TP
+\fIvecName \fBmerge\fR \fIsrcName\fR ?\fIsrcName\fR?...
+Merges the named vectors into a single vector. The resulting
+vector is formed by merging the components of each source vector
+one index at a time.
+.TP
+\fIvecName \fBnotify\fR \fIkeyword\fR
+Controls how vector clients are notified of changes to the vector.
+The exact behavior is determined by \fIkeyword\fR.
+.RS
+.TP 0.75i
+\f(CWalways\fR
+Indicates that clients are to be notified immediately whenever the
+vector is updated.
+.TP
+\f(CWnever\fR
+Indicates that no clients are to be notified.
+.TP
+\f(CWwhenidle\fR
+Indicates that clients are to be notified at the next idle point
+whenever the vector is updated.
+.TP
+\f(CWnow\fR
+If any client notifications is currently pending, they are notified
+immediately.
+.TP
+\f(CWcancel\fR
+Cancels pending notifications of clients using the vector.
+.TP
+\f(CWpending\fR
+Returns \f(CW1\fR if a client notification is pending, and \f(CW0\fR otherwise.
+.RE
+.TP
+\fIvecName \fBoffset\fR ?\fIvalue\fR?
+Shifts the indices of the vector by the amount specified by \fIvalue\fR.
+\fIValue\fR is an integer number. If no \fIvalue\fR argument is
+given, the current offset is returned.
+.TP
+\fIvecName \fBpopulate\fR \fIdestName\fR ?\fIdensity\fR?
+Creates a vector \fIdestName\fR which is a superset of \fIvecName\fR.
+\fIDestName\fR will include all the components of \fIvecName\fR, in
+addition the interval between each of the original components will
+contain a \fIdensity\fR number of new components, whose values are
+evenly distributed between the original components values. This is
+useful for generating abscissas to be interpolated along a spline.
+.TP
+\fIvecName \fBrange\fR \fIfirstIndex\fR ?\fIlastIndex\fR?...
+Returns a list of numeric values representing the vector components
+between two indices. Both \fIfirstIndex\fR and \fIlastIndex\fR are
+indices representing the range of components to be returned. If
+\fIlastIndex\fR is less than \fIfirstIndex\fR, the components are
+listed in reverse order.
+.TP
+\fIvecName \fBsearch\fR \fIvalue\fR ?\fIvalue\fR?
+Searches for a value or range of values among the components of
+\fIvecName\fR. If one \fIvalue\fR argument is given, a list of
+indices of the components which equal \fIvalue\fR is returned. If a
+second \fIvalue\fR is also provided, then the indices of all
+components which lie within the range of the two values are returned.
+If no components are found, then \f(CW""\fR is returned.
+.TP
+\fIvecName \fBset\fR \fIitem\fR
+Resets the components of the vector to \fIitem\fR. \fIItem\fR can
+be either a list of numeric expressions or another vector.
+.TP
+\fIvecName \fBseq\fR \fIstart\fR ?\fIfinish\fR? ?\fIstep\fR?
+Generates a sequence of values starting with the value \fIstart\fR.
+\fIFinish\fR indicates the terminating value of the sequence.
+The vector is automatically resized to contain just the sequence.
+If three arguments are present, \fIstep\fR designates the interval.
+.sp
+With only two arguments (no \fIfinish\fR argument), the sequence will
+continue until the vector is filled. With one argument, the interval
+defaults to 1.0.
+.TP
+\fIvecName \fBsort\fR ?\fB-reverse\fR? ?\fIargName\fR?...
+Sorts the vector \fIvecName\fR in increasing order. If the
+\fB-reverse\fR flag is present, the vector is sorted in decreasing
+order. If other arguments \fIargName\fR are present, they are the
+names of vectors which will be rearranged in the same manner as
+\fIvecName\fR. Each vector must be the same length as \fIvecName\fR.
+You could use this to sort the x vector of a graph, while still
+retaining the same x,y coordinate pairs in a y vector.
+.TP
+\fIvecName \fBvariable\fR \fIvarName\fR
+Maps a Tcl variable to the vector, creating another means for
+accessing the vector. The variable \fIvarName\fR can't already
+exist. This overrides any current variable mapping the vector
+may have.
+.RE
+.SH C LANGUAGE API
+You can create, modify, and destroy vectors from C code, using
+library routines.
+You need to include the header file \f(CWblt.h\fR. It contains the
+definition of the structure \fBBlt_Vector\fR, which represents the
+vector. It appears below.
+.CS
+\fRtypedef struct {
+ double *\fIvalueArr\fR;
+ int \fInumValues\fR;
+ int \fIarraySize\fR;
+ double \fImin\fR, \fImax\fR;
+} \fBBlt_Vector\fR;
+.CE
+The field \fIvalueArr\fR points to memory holding the vector
+components. The components are stored in a double precision array,
+whose size size is represented by \fIarraySize\fR. \fINumValues\fR is
+the length of vector. The size of the array is always equal to or
+larger than the length of the vector. \fIMin\fR and \fImax\fR are
+minimum and maximum component values.
+.SH LIBRARY ROUTINES
+The following routines are available from C to manage vectors.
+Vectors are identified by the vector name.
+.PP
+\fBBlt_CreateVector\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_CreateVector\fR (\fIinterp\fR, \fIvecName\fR, \fIlength\fR, \fIvecPtrPtr\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+char *\fIvecName\fR;
+int \fIlength\fR;
+Blt_Vector **\fIvecPtrPtr\fR;
+.RE
+.CE
+.TP
+Description:
+Creates a new vector \fIvecName\fR\fR with a length of \fIlength\fR.
+\fBBlt_CreateVector\fR creates both a new Tcl command and array
+variable \fIvecName\fR. Neither a command nor variable named
+\fIvecName\fR can already exist. A pointer to the vector is
+placed into \fIvecPtrPtr\fR.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully created. If
+\fIlength\fR is negative, a Tcl variable or command \fIvecName\fR
+already exists, or memory cannot be allocated for the vector, then
+\f(CWTCL_ERROR\fR is returned and \fIinterp->result\fR will contain an
+error message.
+.RE
+.sp
+.PP
+\fBBlt_DeleteVectorByName\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_DeleteVectorByName\fR (\fIinterp\fR, \fIvecName\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+char *\fIvecName\fR;
+.RE
+.CE
+.TP 1i
+Description:
+Removes the vector \fIvecName\fR. \fIVecName\fR is the name of a vector
+which must already exist. Both the Tcl command and array variable
+\fIvecName\fR are destroyed. All clients of the vector will be notified
+immediately that the vector has been destroyed.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully deleted. If
+\fIvecName\fR is not the name a vector, then \f(CWTCL_ERROR\fR is returned
+and \fIinterp->result\fR will contain an error message.
+.RE
+.sp
+.PP
+\fBBlt_DeleteVector\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_DeleteVector\fR (\fIvecPtr\fR)
+.RS 1.25i
+Blt_Vector *\fIvecPtr\fR;
+.RE
+.CE
+.TP 1i
+Description:
+Removes the vector pointed to by \fIvecPtr\fR. \fIVecPtr\fR is a
+pointer to a vector, typically set by \fBBlt_GetVector\fR or
+\fBBlt_CreateVector\fR. Both the Tcl command and array variable of
+the vector are destroyed. All clients of the vector will be notified
+immediately that the vector has been destroyed.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully deleted. If
+\fIvecName\fR is not the name a vector, then \f(CWTCL_ERROR\fR is returned
+and \fIinterp->result\fR will contain an error message.
+.RE
+.sp
+.PP
+\fBBlt_GetVector\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_GetVector\fR (\fIinterp\fR, \fIvecName\fR, \fIvecPtrPtr\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+char *\fIvecName\fR;
+Blt_Vector **\fIvecPtrPtr\fR;
+.RE
+.CE
+.TP 1i
+Description:
+Retrieves the vector \fIvecName\fR. \fIVecName\fR is the name of a
+vector which must already exist. \fIVecPtrPtr\fR will point be set to
+the address of the vector.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully retrieved. If
+\fIvecName\fR is not the name of a vector, then \f(CWTCL_ERROR\fR is
+returned and \fIinterp->result\fR will contain an error message.
+.RE
+.sp
+.PP
+\fBBlt_ResetVector\fR
+.PP
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_ResetVector\fR (\fIvecPtr\fR, \fIdataArr\fR,
+ \fInumValues\fR, \fIarraySize\fR, \fIfreeProc\fR)
+.RS 1.25i
+Blt_Vector *\fIvecPtr\fR;
+double *\fIdataArr\fR;
+int *\fInumValues\fR;
+int *\fIarraySize\fR;
+Tcl_FreeProc *\fIfreeProc\fR;
+.RE
+.CE
+.TP
+Description:
+Resets the components of the vector pointed to by \fIvecPtr\fR.
+Calling \fBBlt_ResetVector\fR will trigger the vector to dispatch
+notifications to its clients. \fIDataArr\fR is the array of doubles
+which represents the vector data. \fINumValues\fR is the number of
+elements in the array. \fIArraySize\fR is the actual size of the array
+(the array may be bigger than the number of values stored in
+it). \fIFreeProc\fP indicates how the storage for the vector component
+array (\fIdataArr\fR) was allocated. It is used to determine how to
+reallocate memory when the vector is resized or destroyed. It must be
+\f(CWTCL_DYNAMIC\fR, \f(CWTCL_STATIC\fR, \f(CWTCL_VOLATILE\fR, or a pointer
+to a function to free the memory allocated for the vector array. If
+\fIfreeProc\fR is \f(CWTCL_VOLATILE\fR, it indicates that \fIdataArr\fR
+must be copied and saved. If \fIfreeProc\fR is \f(CWTCL_DYNAMIC\fR, it
+indicates that \fIdataArr\fR was dynamically allocated and that Tcl
+should free \fIdataArr\fR if necessary. \f(CWStatic\fR indicates that
+nothing should be done to release storage for \fIdataArr\fR.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully resized. If
+\fInewSize\fR is negative, a vector \fIvecName\fR does not exist, or
+memory cannot be allocated for the vector, then \f(CWTCL_ERROR\fR is
+returned and \fIinterp->result\fR will contain an error message.
+.RE
+.sp
+.PP
+\fBBlt_ResizeVector\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_ResizeVector\fR (\fIvecPtr\fR, \fInewSize\fR)
+.RS 1.25i
+Blt_Vector *\fIvecPtr\fR;
+int \fInewSize\fR;
+.RE
+.CE
+.TP
+Description:
+Resets the length of the vector pointed to by \fIvecPtr\fR to
+\fInewSize\fR. If \fInewSize\fR is smaller than the current size of
+the vector, it is truncated. If \fInewSize\fR is greater, the vector
+is extended and the new components are initialized to \f(CW0.0\fR.
+Calling \fBBlt_ResetVector\fR will trigger the vector to dispatch
+notifications.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully resized. If
+\fInewSize\fR is negative or memory can not be allocated for the vector,
+then \f(CWTCL_ERROR\fR is returned and \fIinterp->result\fR will contain
+an error message.
+.sp
+.PP
+\fBBlt_VectorExists\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_VectorExists\fR (\fIinterp\fR, \fIvecName\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+char *\fIvecName\fR;
+.RE
+.CE
+.TP
+Description:
+Indicates if a vector named \fIvecName\fR exists in \fIinterp\fR.
+.TP
+Results:
+Returns \f(CW1\fR if a vector \fIvecName\fR exists and \f(CW0\fR otherwise.
+.RE
+.sp
+.PP
+If your application needs to be notified when a vector changes, it can
+allocate a unique \fIclient identifier\fR for itself. Using this
+identifier, you can then register a call-back to be made whenever the
+vector is updated or destroyed. By default, the call-backs are made at
+the next idle point. This can be changed to occur at the time the
+vector is modified. An application can allocate more than one
+identifier for any vector. When the client application is done with
+the vector, it should free the identifier.
+.PP
+The call-back routine must of the following type.
+.CS
+.RS
+.sp
+typedef void (\fBBlt_VectorChangedProc\fR) (Tcl_Interp *\fIinterp\fR,
+.RS .25i
+ClientData \fIclientData\fR, Blt_VectorNotify \fInotify\fR);
+.RE
+.sp
+.RE
+.CE
+.fi
+\fIClientData\fR is passed to this routine whenever it is called. You
+can use this to pass information to the call-back. The \fInotify\fR
+argument indicates whether the vector has been updated of destroyed. It
+is an enumerated type.
+.CS
+.RS
+.sp
+typedef enum {
+ \f(CWBLT_VECTOR_NOTIFY_UPDATE\fR=1,
+ \f(CWBLT_VECTOR_NOTIFY_DESTROY\fR=2
+} \fBBlt_VectorNotify\fR;
+.sp
+.RE
+.CE
+.PP
+\fBBlt_AllocVectorId\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+Blt_VectorId \fBBlt_AllocVectorId\fR (\fIinterp\fR, \fIvecName\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+char *\fIvecName\fR;
+.RE
+.CE
+.TP
+Description:
+Allocates an client identifier for with the vector \fIvecName\fR.
+This identifier can be used to specify a call-back which is triggered
+when the vector is updated or destroyed.
+.TP
+Results:
+Returns a client identifier if successful. If \fIvecName\fR is not
+the name of a vector, then \f(CWNULL\fR is returned and
+\fIinterp->result\fR will contain an error message.
+.RE
+.sp
+.PP
+\fBBlt_GetVectorById\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+int \fBBlt_GetVector\fR (\fIinterp\fR, \fIclientId\fR, \fIvecPtrPtr\fR)
+.RS 1.25i
+Tcl_Interp *\fIinterp\fR;
+Blt_VectorId \fIclientId\fR;
+Blt_Vector **\fIvecPtrPtr\fR;
+.RE
+.CE
+.TP 1i
+Description:
+Retrieves the vector used by \fIclientId\fR. \fIClientId\fR is a valid
+vector client identifier allocated by \fBBlt_AllocVectorId\fR.
+\fIVecPtrPtr\fR will point be set to the address of the vector.
+.TP
+Results:
+Returns \f(CWTCL_OK\fR if the vector is successfully retrieved.
+.RE
+.sp
+.PP
+\fBBlt_SetVectorChangedProc\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+void \fBBlt_SetVectorChangedProc\fR (\fIclientId\fR, \fIproc\fR, \fIclientData\fR);
+.RS 1.25i
+Blt_VectorId \fIclientId\fR;
+Blt_VectorChangedProc *\fIproc\fR;
+ClientData *\fIclientData\fR;
+.RE
+.CE
+.TP
+Description:
+Specifies a call-back routine to be called whenever the vector
+associated with \fIclientId\fR is updated or deleted. \fIProc\fR is a
+pointer to call-back routine and must be of the type
+\fBBlt_VectorChangedProc\fR. \fIClientData\fR is a one-word value to
+be passed to the routine when it is invoked. If \fIproc\fR is
+\f(CWNULL\fR, then the client is not notified.
+.TP
+Results:
+The designated call-back procedure will be invoked when the vector is
+updated or destroyed.
+.RE
+.sp
+.PP
+\fBBlt_FreeVectorId\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+void \fBBlt_FreeVectorId\fR (\fIclientId\fR);
+.RS 1.25i
+Blt_VectorId \fIclientId\fR;
+.RE
+.CE
+.TP
+Description:
+Frees the client identifier. Memory allocated for the identifier
+is released. The client will no longer be notified when the
+vector is modified.
+.TP
+Results:
+The designated call-back procedure will be no longer be invoked when
+the vector is updated or destroyed.
+.RE
+.sp
+.PP
+\fBBlt_NameOfVectorId\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+char *\fBBlt_NameOfVectorId\fR (\fIclientId\fR);
+.RS 1.25i
+Blt_VectorId \fIclientId\fR;
+.RE
+.CE
+.TP
+Description:
+Retrieves the name of the vector associated with the client identifier
+\fIclientId\fR.
+.TP
+Results:
+Returns the name of the vector associated with \fIclientId\fR. If
+\fIclientId\fR is not an identifier or the vector has been destroyed,
+\f(CWNULL\fR is returned.
+.RE
+.sp
+.PP
+\fBBlt_InstallIndexProc\fR
+.RS .25i
+.TP 1i
+Synopsis:
+.CS
+void \fBBlt_InstallIndexProc\fR (\fIindexName\fR, \fIprocPtr\fR)
+.RS 1.25i
+char *\fIindexName\fR;
+Blt_VectorIndexProc *\fIprocPtr\fR;
+.RE
+.CE
+.TP
+Description:
+Registers a function to be called to retrieved the index \fIindexName\fR
+from the vector's array variable.
+.sp
+typedef double Blt_VectorIndexProc(Vector *vecPtr);
+.sp
+The function will be passed a pointer to the vector. The function must
+return a double representing the value at the index.
+.TP
+Results:
+The new index is installed into the vector.
+.RE
+.RE
+.SH C API EXAMPLE
+The following example opens a file of binary data and stores it in an
+array of doubles. The array size is computed from the size of the
+file. If the vector "data" exists, calling \fBBlt_VectorExists\fR,
+\fBBlt_GetVector\fR is called to get the pointer to the vector.
+Otherwise the routine \fBBlt_CreateVector\fR is called to create a new
+vector and returns a pointer to it. Just like the Tcl interface, both
+a new Tcl command and array variable are created when a new vector is
+created. It doesn't make any difference what the initial size of the
+vector is since it will be reset shortly. The vector is updated when
+\fBlt_ResetVector\fR is called. Blt_ResetVector makes the changes
+visible to the Tcl interface and other vector clients (such as a graph
+widget).
+.sp
+.CS
+#include <tcl.h>
+#include <blt.h>
+...
+Blt_Vector *vecPtr;
+double *newArr;
+FILE *f;
+struct stat statBuf;
+int numBytes, numValues;
+
+f = fopen("binary.dat", "r");
+fstat(fileno(f), &statBuf);
+numBytes = (int)statBuf.st_size;
+
+/* Allocate an array big enough to hold all the data */
+newArr = (double *)malloc(numBytes);
+numValues = numBytes / sizeof(double);
+fread((void *)newArr, numValues, sizeof(double), f);
+fclose(f);
+
+if (Blt_VectorExists(interp, "data")) {
+ if (Blt_GetVector(interp, "data", &vecPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+} else {
+ if (Blt_CreateVector(interp, "data", 0, &vecPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+}
+/*
+ * Reset the vector. Clients will be notified when Tk is idle.
+ * TCL_DYNAMIC tells the vector to free the memory allocated
+ * if it needs to reallocate or destroy the vector.
+ */
+if (Blt_ResetVector(vecPtr, newArr, numValues, numValues,
+ TCL_DYNAMIC) != TCL_OK) {
+ return TCL_ERROR;
+}
+.CE
+.SH "INCOMPATIBILITIES"
+In previous versions, if the array variable isn't global
+(i.e. local to a Tcl procedure), the vector is automatically
+destroyed when the procedure returns.
+.CS
+proc doit {} {
+ # Temporary vector x
+ vector x(10)
+ set x(9) 2.0
+ ...
+}
+.CE
+.PP
+This has changed. Variables are not automatically destroyed when
+their variable is unset. You can restore the old behavior by
+setting the "-watchunset" switch.
+.CE
+.SH KEYWORDS
+vector, graph, widget
diff --git a/tlt3.0/library/afm/AvantGarde-Book.afm b/tlt3.0/library/afm/AvantGarde-Book.afm
new file mode 100644
index 0000000..1e60fee
--- /dev/null
+++ b/tlt3.0/library/afm/AvantGarde-Book.afm
@@ -0,0 +1,574 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Mar 4 13:37:31 1991
+Comment UniqueID 34364
+Comment VMusage 24225 31117
+FontName AvantGarde-Book
+FullName ITC Avant Garde Gothic Book
+FamilyName ITC Avant Garde Gothic
+Weight Book
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -113 -222 1148 955
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.ITC Avant Garde Gothic is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 740
+XHeight 547
+Ascender 740
+Descender -192
+StartCharMetrics 228
+C 32 ; WX 277 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 295 ; N exclam ; B 111 0 185 740 ;
+C 34 ; WX 309 ; N quotedbl ; B 36 444 273 740 ;
+C 35 ; WX 554 ; N numbersign ; B 33 0 521 740 ;
+C 36 ; WX 554 ; N dollar ; B 70 -70 485 811 ;
+C 37 ; WX 775 ; N percent ; B 21 -13 753 751 ;
+C 38 ; WX 757 ; N ampersand ; B 56 -12 736 753 ;
+C 39 ; WX 351 ; N quoteright ; B 94 546 256 740 ;
+C 40 ; WX 369 ; N parenleft ; B 47 -205 355 757 ;
+C 41 ; WX 369 ; N parenright ; B 14 -205 322 757 ;
+C 42 ; WX 425 ; N asterisk ; B 58 446 367 740 ;
+C 43 ; WX 606 ; N plus ; B 51 0 555 506 ;
+C 44 ; WX 277 ; N comma ; B 14 -67 176 126 ;
+C 45 ; WX 332 ; N hyphen ; B 30 248 302 315 ;
+C 46 ; WX 277 ; N period ; B 102 0 176 126 ;
+C 47 ; WX 437 ; N slash ; B 44 -100 403 740 ;
+C 48 ; WX 554 ; N zero ; B 29 -13 525 753 ;
+C 49 ; WX 554 ; N one ; B 135 0 336 740 ;
+C 50 ; WX 554 ; N two ; B 40 0 514 753 ;
+C 51 ; WX 554 ; N three ; B 34 -13 506 753 ;
+C 52 ; WX 554 ; N four ; B 14 0 528 740 ;
+C 53 ; WX 554 ; N five ; B 26 -13 530 740 ;
+C 54 ; WX 554 ; N six ; B 24 -13 530 739 ;
+C 55 ; WX 554 ; N seven ; B 63 0 491 740 ;
+C 56 ; WX 554 ; N eight ; B 41 -13 513 753 ;
+C 57 ; WX 554 ; N nine ; B 24 0 530 752 ;
+C 58 ; WX 277 ; N colon ; B 102 0 176 548 ;
+C 59 ; WX 277 ; N semicolon ; B 14 -67 176 548 ;
+C 60 ; WX 606 ; N less ; B 46 -8 554 514 ;
+C 61 ; WX 606 ; N equal ; B 51 118 555 388 ;
+C 62 ; WX 606 ; N greater ; B 52 -8 560 514 ;
+C 63 ; WX 591 ; N question ; B 64 0 526 752 ;
+C 64 ; WX 867 ; N at ; B 65 -13 803 753 ;
+C 65 ; WX 740 ; N A ; B 12 0 729 740 ;
+C 66 ; WX 574 ; N B ; B 74 0 544 740 ;
+C 67 ; WX 813 ; N C ; B 43 -13 771 752 ;
+C 68 ; WX 744 ; N D ; B 74 0 699 740 ;
+C 69 ; WX 536 ; N E ; B 70 0 475 740 ;
+C 70 ; WX 485 ; N F ; B 70 0 444 740 ;
+C 71 ; WX 872 ; N G ; B 40 -13 828 753 ;
+C 72 ; WX 683 ; N H ; B 76 0 607 740 ;
+C 73 ; WX 226 ; N I ; B 76 0 150 740 ;
+C 74 ; WX 482 ; N J ; B 6 -13 402 740 ;
+C 75 ; WX 591 ; N K ; B 81 0 591 740 ;
+C 76 ; WX 462 ; N L ; B 82 0 462 740 ;
+C 77 ; WX 919 ; N M ; B 76 0 843 740 ;
+C 78 ; WX 740 ; N N ; B 75 0 664 740 ;
+C 79 ; WX 869 ; N O ; B 43 -13 826 753 ;
+C 80 ; WX 592 ; N P ; B 75 0 564 740 ;
+C 81 ; WX 871 ; N Q ; B 40 -13 837 753 ;
+C 82 ; WX 607 ; N R ; B 70 0 572 740 ;
+C 83 ; WX 498 ; N S ; B 22 -13 473 753 ;
+C 84 ; WX 426 ; N T ; B 6 0 419 740 ;
+C 85 ; WX 655 ; N U ; B 75 -13 579 740 ;
+C 86 ; WX 702 ; N V ; B 8 0 693 740 ;
+C 87 ; WX 960 ; N W ; B 11 0 950 740 ;
+C 88 ; WX 609 ; N X ; B 8 0 602 740 ;
+C 89 ; WX 592 ; N Y ; B 1 0 592 740 ;
+C 90 ; WX 480 ; N Z ; B 12 0 470 740 ;
+C 91 ; WX 351 ; N bracketleft ; B 133 -179 337 753 ;
+C 92 ; WX 605 ; N backslash ; B 118 -100 477 740 ;
+C 93 ; WX 351 ; N bracketright ; B 14 -179 218 753 ;
+C 94 ; WX 606 ; N asciicircum ; B 53 307 553 740 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 351 ; N quoteleft ; B 95 546 257 740 ;
+C 97 ; WX 683 ; N a ; B 42 -13 621 561 ;
+C 98 ; WX 682 ; N b ; B 68 -13 647 740 ;
+C 99 ; WX 647 ; N c ; B 41 -13 607 561 ;
+C 100 ; WX 685 ; N d ; B 39 -13 618 740 ;
+C 101 ; WX 650 ; N e ; B 38 -13 608 561 ;
+C 102 ; WX 314 ; N f ; B 19 0 314 753 ; L i fi ; L l fl ;
+C 103 ; WX 673 ; N g ; B 37 -215 606 561 ;
+C 104 ; WX 610 ; N h ; B 62 0 543 740 ;
+C 105 ; WX 200 ; N i ; B 65 0 135 740 ;
+C 106 ; WX 203 ; N j ; B -44 -192 137 740 ;
+C 107 ; WX 502 ; N k ; B 70 0 498 740 ;
+C 108 ; WX 200 ; N l ; B 65 0 135 740 ;
+C 109 ; WX 938 ; N m ; B 66 0 872 561 ;
+C 110 ; WX 610 ; N n ; B 65 0 546 561 ;
+C 111 ; WX 655 ; N o ; B 42 -13 614 561 ;
+C 112 ; WX 682 ; N p ; B 64 -192 643 561 ;
+C 113 ; WX 682 ; N q ; B 37 -192 616 561 ;
+C 114 ; WX 301 ; N r ; B 65 0 291 561 ;
+C 115 ; WX 388 ; N s ; B 24 -13 364 561 ;
+C 116 ; WX 339 ; N t ; B 14 0 330 740 ;
+C 117 ; WX 608 ; N u ; B 62 -13 541 547 ;
+C 118 ; WX 554 ; N v ; B 7 0 546 547 ;
+C 119 ; WX 831 ; N w ; B 13 0 820 547 ;
+C 120 ; WX 480 ; N x ; B 12 0 468 547 ;
+C 121 ; WX 536 ; N y ; B 15 -192 523 547 ;
+C 122 ; WX 425 ; N z ; B 10 0 415 547 ;
+C 123 ; WX 351 ; N braceleft ; B 70 -189 331 740 ;
+C 124 ; WX 672 ; N bar ; B 299 -100 373 740 ;
+C 125 ; WX 351 ; N braceright ; B 20 -189 281 740 ;
+C 126 ; WX 606 ; N asciitilde ; B 72 179 534 319 ;
+C 161 ; WX 295 ; N exclamdown ; B 110 -192 184 548 ;
+C 162 ; WX 554 ; N cent ; B 48 62 510 707 ;
+C 163 ; WX 554 ; N sterling ; B 4 0 552 753 ;
+C 164 ; WX 166 ; N fraction ; B -113 0 280 740 ;
+C 165 ; WX 554 ; N yen ; B 4 0 550 740 ;
+C 166 ; WX 554 ; N florin ; B -12 -153 518 818 ;
+C 167 ; WX 615 ; N section ; B 85 -141 529 753 ;
+C 168 ; WX 554 ; N currency ; B 8 42 546 580 ;
+C 169 ; WX 198 ; N quotesingle ; B 59 444 140 740 ;
+C 170 ; WX 502 ; N quotedblleft ; B 97 546 406 740 ;
+C 171 ; WX 425 ; N guillemotleft ; B 40 81 386 481 ;
+C 172 ; WX 251 ; N guilsinglleft ; B 40 81 212 481 ;
+C 173 ; WX 251 ; N guilsinglright ; B 39 81 211 481 ;
+C 174 ; WX 487 ; N fi ; B 19 0 422 753 ;
+C 175 ; WX 485 ; N fl ; B 19 0 420 753 ;
+C 177 ; WX 500 ; N endash ; B 35 248 465 315 ;
+C 178 ; WX 553 ; N dagger ; B 59 -133 493 740 ;
+C 179 ; WX 553 ; N daggerdbl ; B 59 -133 493 740 ;
+C 180 ; WX 277 ; N periodcentered ; B 102 190 176 316 ;
+C 182 ; WX 564 ; N paragraph ; B 22 -110 551 740 ;
+C 183 ; WX 606 ; N bullet ; B 150 222 455 532 ;
+C 184 ; WX 354 ; N quotesinglbase ; B 89 -68 251 126 ;
+C 185 ; WX 502 ; N quotedblbase ; B 89 -68 399 126 ;
+C 186 ; WX 484 ; N quotedblright ; B 96 546 405 740 ;
+C 187 ; WX 425 ; N guillemotright ; B 39 81 385 481 ;
+C 188 ; WX 1000 ; N ellipsis ; B 130 0 870 126 ;
+C 189 ; WX 1174 ; N perthousand ; B 25 -13 1148 751 ;
+C 191 ; WX 591 ; N questiondown ; B 65 -205 527 548 ;
+C 193 ; WX 378 ; N grave ; B 69 619 300 786 ;
+C 194 ; WX 375 ; N acute ; B 78 619 309 786 ;
+C 195 ; WX 502 ; N circumflex ; B 74 639 428 764 ;
+C 196 ; WX 439 ; N tilde ; B 47 651 392 754 ;
+C 197 ; WX 485 ; N macron ; B 73 669 411 736 ;
+C 198 ; WX 453 ; N breve ; B 52 651 401 754 ;
+C 199 ; WX 222 ; N dotaccent ; B 74 639 148 765 ;
+C 200 ; WX 369 ; N dieresis ; B 73 639 295 765 ;
+C 202 ; WX 332 ; N ring ; B 62 600 269 807 ;
+C 203 ; WX 324 ; N cedilla ; B 80 -222 254 0 ;
+C 205 ; WX 552 ; N hungarumlaut ; B 119 605 453 800 ;
+C 206 ; WX 302 ; N ogonek ; B 73 -191 228 0 ;
+C 207 ; WX 502 ; N caron ; B 68 639 423 764 ;
+C 208 ; WX 1000 ; N emdash ; B 35 248 965 315 ;
+C 225 ; WX 992 ; N AE ; B -20 0 907 740 ;
+C 227 ; WX 369 ; N ordfeminine ; B -3 407 356 753 ;
+C 232 ; WX 517 ; N Lslash ; B 59 0 517 740 ;
+C 233 ; WX 868 ; N Oslash ; B 43 -83 826 819 ;
+C 234 ; WX 1194 ; N OE ; B 45 -13 1142 753 ;
+C 235 ; WX 369 ; N ordmasculine ; B 12 407 356 753 ;
+C 241 ; WX 1157 ; N ae ; B 34 -13 1113 561 ;
+C 245 ; WX 200 ; N dotlessi ; B 65 0 135 547 ;
+C 248 ; WX 300 ; N lslash ; B 43 0 259 740 ;
+C 249 ; WX 653 ; N oslash ; B 41 -64 613 614 ;
+C 250 ; WX 1137 ; N oe ; B 34 -13 1104 561 ;
+C 251 ; WX 554 ; N germandbls ; B 61 -13 525 753 ;
+C -1 ; WX 650 ; N ecircumflex ; B 38 -13 608 764 ;
+C -1 ; WX 650 ; N edieresis ; B 38 -13 608 765 ;
+C -1 ; WX 683 ; N aacute ; B 42 -13 621 786 ;
+C -1 ; WX 747 ; N registered ; B -9 -12 755 752 ;
+C -1 ; WX 200 ; N icircumflex ; B -77 0 277 764 ;
+C -1 ; WX 608 ; N udieresis ; B 62 -13 541 765 ;
+C -1 ; WX 655 ; N ograve ; B 42 -13 614 786 ;
+C -1 ; WX 608 ; N uacute ; B 62 -13 541 786 ;
+C -1 ; WX 608 ; N ucircumflex ; B 62 -13 541 764 ;
+C -1 ; WX 740 ; N Aacute ; B 12 0 729 949 ;
+C -1 ; WX 200 ; N igrave ; B -60 0 171 786 ;
+C -1 ; WX 226 ; N Icircumflex ; B -64 0 290 927 ;
+C -1 ; WX 647 ; N ccedilla ; B 41 -222 607 561 ;
+C -1 ; WX 683 ; N adieresis ; B 42 -13 621 765 ;
+C -1 ; WX 536 ; N Ecircumflex ; B 70 0 475 927 ;
+C -1 ; WX 388 ; N scaron ; B 11 -13 366 764 ;
+C -1 ; WX 682 ; N thorn ; B 64 -192 643 740 ;
+C -1 ; WX 1000 ; N trademark ; B 9 296 816 740 ;
+C -1 ; WX 650 ; N egrave ; B 38 -13 608 786 ;
+C -1 ; WX 332 ; N threesuperior ; B 18 289 318 747 ;
+C -1 ; WX 425 ; N zcaron ; B 10 0 415 764 ;
+C -1 ; WX 683 ; N atilde ; B 42 -13 621 754 ;
+C -1 ; WX 683 ; N aring ; B 42 -13 621 807 ;
+C -1 ; WX 655 ; N ocircumflex ; B 42 -13 614 764 ;
+C -1 ; WX 536 ; N Edieresis ; B 70 0 475 928 ;
+C -1 ; WX 831 ; N threequarters ; B 46 0 784 747 ;
+C -1 ; WX 536 ; N ydieresis ; B 15 -192 523 765 ;
+C -1 ; WX 536 ; N yacute ; B 15 -192 523 786 ;
+C -1 ; WX 200 ; N iacute ; B 31 0 262 786 ;
+C -1 ; WX 740 ; N Acircumflex ; B 12 0 729 927 ;
+C -1 ; WX 655 ; N Uacute ; B 75 -13 579 949 ;
+C -1 ; WX 650 ; N eacute ; B 38 -13 608 786 ;
+C -1 ; WX 869 ; N Ograve ; B 43 -13 826 949 ;
+C -1 ; WX 683 ; N agrave ; B 42 -13 621 786 ;
+C -1 ; WX 655 ; N Udieresis ; B 75 -13 579 928 ;
+C -1 ; WX 683 ; N acircumflex ; B 42 -13 621 764 ;
+C -1 ; WX 226 ; N Igrave ; B -47 0 184 949 ;
+C -1 ; WX 332 ; N twosuperior ; B 19 296 318 747 ;
+C -1 ; WX 655 ; N Ugrave ; B 75 -13 579 949 ;
+C -1 ; WX 831 ; N onequarter ; B 100 0 729 740 ;
+C -1 ; WX 655 ; N Ucircumflex ; B 75 -13 579 927 ;
+C -1 ; WX 498 ; N Scaron ; B 22 -13 473 927 ;
+C -1 ; WX 226 ; N Idieresis ; B 2 0 224 928 ;
+C -1 ; WX 200 ; N idieresis ; B -11 0 211 765 ;
+C -1 ; WX 536 ; N Egrave ; B 70 0 475 949 ;
+C -1 ; WX 869 ; N Oacute ; B 43 -13 826 949 ;
+C -1 ; WX 606 ; N divide ; B 51 -13 555 519 ;
+C -1 ; WX 740 ; N Atilde ; B 12 0 729 917 ;
+C -1 ; WX 740 ; N Aring ; B 12 0 729 955 ;
+C -1 ; WX 869 ; N Odieresis ; B 43 -13 826 928 ;
+C -1 ; WX 740 ; N Adieresis ; B 12 0 729 928 ;
+C -1 ; WX 740 ; N Ntilde ; B 75 0 664 917 ;
+C -1 ; WX 480 ; N Zcaron ; B 12 0 470 927 ;
+C -1 ; WX 592 ; N Thorn ; B 60 0 549 740 ;
+C -1 ; WX 226 ; N Iacute ; B 44 0 275 949 ;
+C -1 ; WX 606 ; N plusminus ; B 51 -24 555 518 ;
+C -1 ; WX 606 ; N multiply ; B 74 24 533 482 ;
+C -1 ; WX 536 ; N Eacute ; B 70 0 475 949 ;
+C -1 ; WX 592 ; N Ydieresis ; B 1 0 592 928 ;
+C -1 ; WX 332 ; N onesuperior ; B 63 296 198 740 ;
+C -1 ; WX 608 ; N ugrave ; B 62 -13 541 786 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 109 555 388 ;
+C -1 ; WX 610 ; N ntilde ; B 65 0 546 754 ;
+C -1 ; WX 869 ; N Otilde ; B 43 -13 826 917 ;
+C -1 ; WX 655 ; N otilde ; B 42 -13 614 754 ;
+C -1 ; WX 813 ; N Ccedilla ; B 43 -222 771 752 ;
+C -1 ; WX 740 ; N Agrave ; B 12 0 729 949 ;
+C -1 ; WX 831 ; N onehalf ; B 81 0 750 740 ;
+C -1 ; WX 790 ; N Eth ; B 40 0 739 740 ;
+C -1 ; WX 400 ; N degree ; B 56 421 344 709 ;
+C -1 ; WX 592 ; N Yacute ; B 1 0 592 949 ;
+C -1 ; WX 869 ; N Ocircumflex ; B 43 -13 826 927 ;
+C -1 ; WX 655 ; N oacute ; B 42 -13 614 786 ;
+C -1 ; WX 608 ; N mu ; B 80 -184 527 547 ;
+C -1 ; WX 606 ; N minus ; B 51 219 555 287 ;
+C -1 ; WX 655 ; N eth ; B 42 -12 614 753 ;
+C -1 ; WX 655 ; N odieresis ; B 42 -13 614 765 ;
+C -1 ; WX 747 ; N copyright ; B -9 -12 755 752 ;
+C -1 ; WX 672 ; N brokenbar ; B 299 -100 373 740 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 216
+
+KPX A y -62
+KPX A w -65
+KPX A v -70
+KPX A u -20
+KPX A quoteright -100
+KPX A quotedblright -100
+KPX A Y -92
+KPX A W -60
+KPX A V -102
+KPX A U -40
+KPX A T -45
+KPX A Q -40
+KPX A O -50
+KPX A G -40
+KPX A C -40
+
+KPX B A -10
+
+KPX C A -40
+
+KPX D period -20
+KPX D comma -20
+KPX D Y -30
+KPX D W -10
+KPX D V -50
+KPX D A -50
+
+KPX F period -160
+KPX F e -20
+KPX F comma -180
+KPX F a -20
+KPX F A -75
+
+KPX G period -20
+KPX G comma -20
+KPX G Y -20
+
+KPX J period -15
+KPX J a -20
+KPX J A -30
+
+KPX K o -15
+KPX K e -20
+KPX K O -20
+
+KPX L y -23
+KPX L quoteright -130
+KPX L quotedblright -130
+KPX L Y -91
+KPX L W -67
+KPX L V -113
+KPX L T -46
+
+KPX O period -30
+KPX O comma -30
+KPX O Y -30
+KPX O X -30
+KPX O W -20
+KPX O V -60
+KPX O T -30
+KPX O A -60
+
+KPX P period -300
+KPX P o -60
+KPX P e -20
+KPX P comma -280
+KPX P a -20
+KPX P A -114
+
+KPX Q comma 20
+
+KPX R Y -10
+KPX R W 10
+KPX R V -10
+KPX R T 6
+
+KPX S comma 20
+
+KPX T y -50
+KPX T w -55
+KPX T u -46
+KPX T semicolon -29
+KPX T r -30
+KPX T period -91
+KPX T o -70
+KPX T i 10
+KPX T hyphen -75
+KPX T e -49
+KPX T comma -82
+KPX T colon -15
+KPX T a -90
+KPX T O -30
+KPX T A -45
+
+KPX U period -20
+KPX U comma -20
+KPX U A -40
+
+KPX V u -40
+KPX V semicolon -33
+KPX V period -165
+KPX V o -101
+KPX V i -5
+KPX V hyphen -75
+KPX V e -101
+KPX V comma -145
+KPX V colon -18
+KPX V a -104
+KPX V O -60
+KPX V G -20
+KPX V A -102
+
+KPX W y -2
+KPX W u -30
+KPX W semicolon -33
+KPX W period -106
+KPX W o -46
+KPX W i 6
+KPX W hyphen -35
+KPX W e -47
+KPX W comma -106
+KPX W colon -15
+KPX W a -50
+KPX W O -20
+KPX W A -58
+
+KPX Y u -52
+KPX Y semicolon -23
+KPX Y period -175
+KPX Y o -89
+KPX Y hyphen -85
+KPX Y e -89
+KPX Y comma -145
+KPX Y colon -10
+KPX Y a -93
+KPX Y O -30
+KPX Y A -92
+
+KPX a p 20
+KPX a b 20
+
+KPX b y -20
+KPX b v -20
+
+KPX c y -20
+KPX c k -15
+
+KPX comma space -110
+KPX comma quoteright -120
+KPX comma quotedblright -120
+
+KPX e y -20
+KPX e w -20
+KPX e v -20
+
+KPX f period -50
+KPX f o -40
+KPX f l -30
+KPX f i -34
+KPX f f -60
+KPX f e -20
+KPX f dotlessi -34
+KPX f comma -50
+KPX f a -40
+
+KPX g a -15
+
+KPX h y -30
+
+KPX k y -5
+KPX k e -15
+
+KPX m y -20
+KPX m u -20
+KPX m a -20
+
+KPX n y -15
+KPX n v -20
+
+KPX o y -20
+KPX o x -15
+KPX o w -20
+KPX o v -30
+
+KPX p y -20
+
+KPX period space -110
+KPX period quoteright -120
+KPX period quotedblright -120
+
+KPX quotedblleft quoteleft -35
+KPX quotedblleft A -100
+
+KPX quotedblright space -110
+
+KPX quoteleft quoteleft -203
+KPX quoteleft A -100
+
+KPX quoteright v -30
+KPX quoteright t 10
+KPX quoteright space -110
+KPX quoteright s -15
+KPX quoteright r -20
+KPX quoteright quoteright -203
+KPX quoteright quotedblright -35
+KPX quoteright d -110
+
+KPX r y 40
+KPX r v 40
+KPX r u 20
+KPX r t 20
+KPX r s 20
+KPX r q -8
+KPX r period -73
+KPX r p 20
+KPX r o -20
+KPX r n 21
+KPX r m 28
+KPX r l 20
+KPX r k 20
+KPX r i 20
+KPX r hyphen -60
+KPX r g -15
+KPX r e -4
+KPX r d -6
+KPX r comma -75
+KPX r c -20
+KPX r a -20
+
+KPX s period 20
+KPX s comma 20
+
+KPX space quoteleft -110
+KPX space quotedblleft -110
+KPX space Y -60
+KPX space W -25
+KPX space V -50
+KPX space T -25
+KPX space A -20
+
+KPX v period -130
+KPX v o -30
+KPX v e -20
+KPX v comma -100
+KPX v a -30
+
+KPX w period -100
+KPX w o -30
+KPX w h 15
+KPX w e -20
+KPX w comma -90
+KPX w a -30
+
+KPX y period -125
+KPX y o -30
+KPX y e -20
+KPX y comma -110
+KPX y a -30
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 183 163 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 119 163 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 186 163 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 181 163 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 204 148 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 151 163 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 81 163 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 17 163 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 84 163 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 79 163 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -34 163 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -138 163 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -71 163 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -116 163 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 151 163 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 247 163 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 184 163 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 250 163 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 246 163 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 163 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron -2 163 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 160 163 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 77 163 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 143 163 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 119 163 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 129 163 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 112 163 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron -11 163 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 154 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 91 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 157 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 153 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 176 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 122 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 138 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 74 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 141 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 136 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -47 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -151 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -84 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -129 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 86 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 140 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 77 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 143 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 108 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron -57 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 137 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 53 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 120 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 95 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 101 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron -38 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/AvantGarde-BookOblique.afm b/tlt3.0/library/afm/AvantGarde-BookOblique.afm
new file mode 100644
index 0000000..ca315b5
--- /dev/null
+++ b/tlt3.0/library/afm/AvantGarde-BookOblique.afm
@@ -0,0 +1,574 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Mar 4 13:41:11 1991
+Comment UniqueID 34367
+Comment VMusage 6555 39267
+FontName AvantGarde-BookOblique
+FullName ITC Avant Garde Gothic Book Oblique
+FamilyName ITC Avant Garde Gothic
+Weight Book
+ItalicAngle -10.5
+IsFixedPitch false
+FontBBox -113 -222 1279 955
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.ITC Avant Garde Gothic is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 740
+XHeight 547
+Ascender 740
+Descender -192
+StartCharMetrics 228
+C 32 ; WX 277 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 295 ; N exclam ; B 111 0 322 740 ;
+C 34 ; WX 309 ; N quotedbl ; B 130 444 410 740 ;
+C 35 ; WX 554 ; N numbersign ; B 71 0 620 740 ;
+C 36 ; WX 554 ; N dollar ; B 107 -70 581 811 ;
+C 37 ; WX 775 ; N percent ; B 124 -13 787 751 ;
+C 38 ; WX 757 ; N ampersand ; B 92 -12 775 753 ;
+C 39 ; WX 351 ; N quoteright ; B 195 546 393 740 ;
+C 40 ; WX 369 ; N parenleft ; B 89 -205 495 757 ;
+C 41 ; WX 369 ; N parenright ; B -24 -205 382 757 ;
+C 42 ; WX 425 ; N asterisk ; B 170 446 479 740 ;
+C 43 ; WX 606 ; N plus ; B 92 0 608 506 ;
+C 44 ; WX 277 ; N comma ; B 2 -67 199 126 ;
+C 45 ; WX 332 ; N hyphen ; B 76 248 360 315 ;
+C 46 ; WX 277 ; N period ; B 102 0 199 126 ;
+C 47 ; WX 437 ; N slash ; B 25 -100 540 740 ;
+C 48 ; WX 554 ; N zero ; B 71 -13 622 753 ;
+C 49 ; WX 554 ; N one ; B 260 0 473 740 ;
+C 50 ; WX 554 ; N two ; B 40 0 615 753 ;
+C 51 ; WX 554 ; N three ; B 73 -13 565 753 ;
+C 52 ; WX 554 ; N four ; B 39 0 598 740 ;
+C 53 ; WX 554 ; N five ; B 69 -13 605 740 ;
+C 54 ; WX 554 ; N six ; B 65 -13 580 739 ;
+C 55 ; WX 554 ; N seven ; B 110 0 628 740 ;
+C 56 ; WX 554 ; N eight ; B 77 -13 580 753 ;
+C 57 ; WX 554 ; N nine ; B 111 0 626 752 ;
+C 58 ; WX 277 ; N colon ; B 102 0 278 548 ;
+C 59 ; WX 277 ; N semicolon ; B 2 -67 278 548 ;
+C 60 ; WX 606 ; N less ; B 87 -8 649 514 ;
+C 61 ; WX 606 ; N equal ; B 73 118 627 388 ;
+C 62 ; WX 606 ; N greater ; B 51 -8 613 514 ;
+C 63 ; WX 591 ; N question ; B 158 0 628 752 ;
+C 64 ; WX 867 ; N at ; B 126 -13 888 753 ;
+C 65 ; WX 740 ; N A ; B 12 0 729 740 ;
+C 66 ; WX 574 ; N B ; B 74 0 606 740 ;
+C 67 ; WX 813 ; N C ; B 105 -13 870 752 ;
+C 68 ; WX 744 ; N D ; B 74 0 773 740 ;
+C 69 ; WX 536 ; N E ; B 70 0 612 740 ;
+C 70 ; WX 485 ; N F ; B 70 0 581 740 ;
+C 71 ; WX 872 ; N G ; B 103 -13 891 753 ;
+C 72 ; WX 683 ; N H ; B 76 0 744 740 ;
+C 73 ; WX 226 ; N I ; B 76 0 287 740 ;
+C 74 ; WX 482 ; N J ; B 37 -13 539 740 ;
+C 75 ; WX 591 ; N K ; B 81 0 728 740 ;
+C 76 ; WX 462 ; N L ; B 82 0 474 740 ;
+C 77 ; WX 919 ; N M ; B 76 0 980 740 ;
+C 78 ; WX 740 ; N N ; B 75 0 801 740 ;
+C 79 ; WX 869 ; N O ; B 105 -13 901 753 ;
+C 80 ; WX 592 ; N P ; B 75 0 664 740 ;
+C 81 ; WX 871 ; N Q ; B 102 -13 912 753 ;
+C 82 ; WX 607 ; N R ; B 70 0 669 740 ;
+C 83 ; WX 498 ; N S ; B 57 -13 561 753 ;
+C 84 ; WX 426 ; N T ; B 131 0 556 740 ;
+C 85 ; WX 655 ; N U ; B 118 -13 716 740 ;
+C 86 ; WX 702 ; N V ; B 145 0 830 740 ;
+C 87 ; WX 960 ; N W ; B 148 0 1087 740 ;
+C 88 ; WX 609 ; N X ; B 8 0 724 740 ;
+C 89 ; WX 592 ; N Y ; B 138 0 729 740 ;
+C 90 ; WX 480 ; N Z ; B 12 0 596 740 ;
+C 91 ; WX 351 ; N bracketleft ; B 145 -179 477 753 ;
+C 92 ; WX 605 ; N backslash ; B 255 -100 458 740 ;
+C 93 ; WX 351 ; N bracketright ; B -19 -179 312 753 ;
+C 94 ; WX 606 ; N asciicircum ; B 110 307 610 740 ;
+C 95 ; WX 500 ; N underscore ; B -23 -125 486 -75 ;
+C 96 ; WX 351 ; N quoteleft ; B 232 546 358 740 ;
+C 97 ; WX 683 ; N a ; B 88 -13 722 561 ;
+C 98 ; WX 682 ; N b ; B 68 -13 703 740 ;
+C 99 ; WX 647 ; N c ; B 87 -13 678 561 ;
+C 100 ; WX 685 ; N d ; B 85 -13 755 740 ;
+C 101 ; WX 650 ; N e ; B 84 -13 664 561 ;
+C 102 ; WX 314 ; N f ; B 104 0 454 753 ; L i fi ; L l fl ;
+C 103 ; WX 673 ; N g ; B 56 -215 707 561 ;
+C 104 ; WX 610 ; N h ; B 62 0 606 740 ;
+C 105 ; WX 200 ; N i ; B 65 0 272 740 ;
+C 106 ; WX 203 ; N j ; B -80 -192 274 740 ;
+C 107 ; WX 502 ; N k ; B 70 0 588 740 ;
+C 108 ; WX 200 ; N l ; B 65 0 272 740 ;
+C 109 ; WX 938 ; N m ; B 66 0 938 561 ;
+C 110 ; WX 610 ; N n ; B 65 0 609 561 ;
+C 111 ; WX 655 ; N o ; B 88 -13 669 561 ;
+C 112 ; WX 682 ; N p ; B 28 -192 699 561 ;
+C 113 ; WX 682 ; N q ; B 83 -192 717 561 ;
+C 114 ; WX 301 ; N r ; B 65 0 395 561 ;
+C 115 ; WX 388 ; N s ; B 49 -13 424 561 ;
+C 116 ; WX 339 ; N t ; B 104 0 431 740 ;
+C 117 ; WX 608 ; N u ; B 100 -13 642 547 ;
+C 118 ; WX 554 ; N v ; B 108 0 647 547 ;
+C 119 ; WX 831 ; N w ; B 114 0 921 547 ;
+C 120 ; WX 480 ; N x ; B 12 0 569 547 ;
+C 121 ; WX 536 ; N y ; B 97 -192 624 547 ;
+C 122 ; WX 425 ; N z ; B 10 0 498 547 ;
+C 123 ; WX 351 ; N braceleft ; B 115 -189 468 740 ;
+C 124 ; WX 672 ; N bar ; B 280 -100 510 740 ;
+C 125 ; WX 351 ; N braceright ; B -15 -189 338 740 ;
+C 126 ; WX 606 ; N asciitilde ; B 114 179 584 319 ;
+C 161 ; WX 295 ; N exclamdown ; B 74 -192 286 548 ;
+C 162 ; WX 554 ; N cent ; B 115 62 596 707 ;
+C 163 ; WX 554 ; N sterling ; B 29 0 614 753 ;
+C 164 ; WX 166 ; N fraction ; B -113 0 417 740 ;
+C 165 ; WX 554 ; N yen ; B 75 0 687 740 ;
+C 166 ; WX 554 ; N florin ; B -39 -153 669 818 ;
+C 167 ; WX 615 ; N section ; B 118 -141 597 753 ;
+C 168 ; WX 554 ; N currency ; B 24 42 645 580 ;
+C 169 ; WX 198 ; N quotesingle ; B 153 444 277 740 ;
+C 170 ; WX 502 ; N quotedblleft ; B 234 546 507 740 ;
+C 171 ; WX 425 ; N guillemotleft ; B 92 81 469 481 ;
+C 172 ; WX 251 ; N guilsinglleft ; B 92 81 295 481 ;
+C 173 ; WX 251 ; N guilsinglright ; B 60 81 263 481 ;
+C 174 ; WX 487 ; N fi ; B 104 0 559 753 ;
+C 175 ; WX 485 ; N fl ; B 104 0 557 753 ;
+C 177 ; WX 500 ; N endash ; B 81 248 523 315 ;
+C 178 ; WX 553 ; N dagger ; B 146 -133 593 740 ;
+C 179 ; WX 553 ; N daggerdbl ; B 72 -133 593 740 ;
+C 180 ; WX 277 ; N periodcentered ; B 137 190 235 316 ;
+C 182 ; WX 564 ; N paragraph ; B 119 -110 688 740 ;
+C 183 ; WX 606 ; N bullet ; B 217 222 528 532 ;
+C 184 ; WX 354 ; N quotesinglbase ; B 76 -68 274 126 ;
+C 185 ; WX 502 ; N quotedblbase ; B 76 -68 422 126 ;
+C 186 ; WX 484 ; N quotedblright ; B 197 546 542 740 ;
+C 187 ; WX 425 ; N guillemotright ; B 60 81 437 481 ;
+C 188 ; WX 1000 ; N ellipsis ; B 130 0 893 126 ;
+C 189 ; WX 1174 ; N perthousand ; B 128 -13 1182 751 ;
+C 191 ; WX 591 ; N questiondown ; B 64 -205 534 548 ;
+C 193 ; WX 378 ; N grave ; B 204 619 425 786 ;
+C 194 ; WX 375 ; N acute ; B 203 619 444 786 ;
+C 195 ; WX 502 ; N circumflex ; B 192 639 546 764 ;
+C 196 ; WX 439 ; N tilde ; B 179 651 520 754 ;
+C 197 ; WX 485 ; N macron ; B 197 669 547 736 ;
+C 198 ; WX 453 ; N breve ; B 192 651 541 754 ;
+C 199 ; WX 222 ; N dotaccent ; B 192 639 290 765 ;
+C 200 ; WX 369 ; N dieresis ; B 191 639 437 765 ;
+C 202 ; WX 332 ; N ring ; B 191 600 401 807 ;
+C 203 ; WX 324 ; N cedilla ; B 52 -222 231 0 ;
+C 205 ; WX 552 ; N hungarumlaut ; B 239 605 594 800 ;
+C 206 ; WX 302 ; N ogonek ; B 53 -191 202 0 ;
+C 207 ; WX 502 ; N caron ; B 210 639 565 764 ;
+C 208 ; WX 1000 ; N emdash ; B 81 248 1023 315 ;
+C 225 ; WX 992 ; N AE ; B -20 0 1044 740 ;
+C 227 ; WX 369 ; N ordfeminine ; B 102 407 494 753 ;
+C 232 ; WX 517 ; N Lslash ; B 107 0 529 740 ;
+C 233 ; WX 868 ; N Oslash ; B 76 -83 929 819 ;
+C 234 ; WX 1194 ; N OE ; B 107 -13 1279 753 ;
+C 235 ; WX 369 ; N ordmasculine ; B 116 407 466 753 ;
+C 241 ; WX 1157 ; N ae ; B 80 -13 1169 561 ;
+C 245 ; WX 200 ; N dotlessi ; B 65 0 236 547 ;
+C 248 ; WX 300 ; N lslash ; B 95 0 354 740 ;
+C 249 ; WX 653 ; N oslash ; B 51 -64 703 614 ;
+C 250 ; WX 1137 ; N oe ; B 80 -13 1160 561 ;
+C 251 ; WX 554 ; N germandbls ; B 61 -13 578 753 ;
+C -1 ; WX 650 ; N ecircumflex ; B 84 -13 664 764 ;
+C -1 ; WX 650 ; N edieresis ; B 84 -13 664 765 ;
+C -1 ; WX 683 ; N aacute ; B 88 -13 722 786 ;
+C -1 ; WX 747 ; N registered ; B 53 -12 830 752 ;
+C -1 ; WX 200 ; N icircumflex ; B 41 0 395 764 ;
+C -1 ; WX 608 ; N udieresis ; B 100 -13 642 765 ;
+C -1 ; WX 655 ; N ograve ; B 88 -13 669 786 ;
+C -1 ; WX 608 ; N uacute ; B 100 -13 642 786 ;
+C -1 ; WX 608 ; N ucircumflex ; B 100 -13 642 764 ;
+C -1 ; WX 740 ; N Aacute ; B 12 0 729 949 ;
+C -1 ; WX 200 ; N igrave ; B 65 0 296 786 ;
+C -1 ; WX 226 ; N Icircumflex ; B 76 0 439 927 ;
+C -1 ; WX 647 ; N ccedilla ; B 87 -222 678 561 ;
+C -1 ; WX 683 ; N adieresis ; B 88 -13 722 765 ;
+C -1 ; WX 536 ; N Ecircumflex ; B 70 0 612 927 ;
+C -1 ; WX 388 ; N scaron ; B 49 -13 508 764 ;
+C -1 ; WX 682 ; N thorn ; B 28 -192 699 740 ;
+C -1 ; WX 1000 ; N trademark ; B 137 296 953 740 ;
+C -1 ; WX 650 ; N egrave ; B 84 -13 664 786 ;
+C -1 ; WX 332 ; N threesuperior ; B 98 289 408 747 ;
+C -1 ; WX 425 ; N zcaron ; B 10 0 527 764 ;
+C -1 ; WX 683 ; N atilde ; B 88 -13 722 754 ;
+C -1 ; WX 683 ; N aring ; B 88 -13 722 807 ;
+C -1 ; WX 655 ; N ocircumflex ; B 88 -13 669 764 ;
+C -1 ; WX 536 ; N Edieresis ; B 70 0 612 928 ;
+C -1 ; WX 831 ; N threequarters ; B 126 0 825 747 ;
+C -1 ; WX 536 ; N ydieresis ; B 97 -192 624 765 ;
+C -1 ; WX 536 ; N yacute ; B 97 -192 624 786 ;
+C -1 ; WX 200 ; N iacute ; B 65 0 397 786 ;
+C -1 ; WX 740 ; N Acircumflex ; B 12 0 729 927 ;
+C -1 ; WX 655 ; N Uacute ; B 118 -13 716 949 ;
+C -1 ; WX 650 ; N eacute ; B 84 -13 664 786 ;
+C -1 ; WX 869 ; N Ograve ; B 105 -13 901 949 ;
+C -1 ; WX 683 ; N agrave ; B 88 -13 722 786 ;
+C -1 ; WX 655 ; N Udieresis ; B 118 -13 716 928 ;
+C -1 ; WX 683 ; N acircumflex ; B 88 -13 722 764 ;
+C -1 ; WX 226 ; N Igrave ; B 76 0 340 949 ;
+C -1 ; WX 332 ; N twosuperior ; B 74 296 433 747 ;
+C -1 ; WX 655 ; N Ugrave ; B 118 -13 716 949 ;
+C -1 ; WX 831 ; N onequarter ; B 183 0 770 740 ;
+C -1 ; WX 655 ; N Ucircumflex ; B 118 -13 716 927 ;
+C -1 ; WX 498 ; N Scaron ; B 57 -13 593 927 ;
+C -1 ; WX 226 ; N Idieresis ; B 76 0 396 928 ;
+C -1 ; WX 200 ; N idieresis ; B 65 0 353 765 ;
+C -1 ; WX 536 ; N Egrave ; B 70 0 612 949 ;
+C -1 ; WX 869 ; N Oacute ; B 105 -13 901 949 ;
+C -1 ; WX 606 ; N divide ; B 92 -13 608 519 ;
+C -1 ; WX 740 ; N Atilde ; B 12 0 729 917 ;
+C -1 ; WX 740 ; N Aring ; B 12 0 729 955 ;
+C -1 ; WX 869 ; N Odieresis ; B 105 -13 901 928 ;
+C -1 ; WX 740 ; N Adieresis ; B 12 0 729 928 ;
+C -1 ; WX 740 ; N Ntilde ; B 75 0 801 917 ;
+C -1 ; WX 480 ; N Zcaron ; B 12 0 596 927 ;
+C -1 ; WX 592 ; N Thorn ; B 60 0 621 740 ;
+C -1 ; WX 226 ; N Iacute ; B 76 0 440 949 ;
+C -1 ; WX 606 ; N plusminus ; B 47 -24 618 518 ;
+C -1 ; WX 606 ; N multiply ; B 87 24 612 482 ;
+C -1 ; WX 536 ; N Eacute ; B 70 0 612 949 ;
+C -1 ; WX 592 ; N Ydieresis ; B 138 0 729 928 ;
+C -1 ; WX 332 ; N onesuperior ; B 190 296 335 740 ;
+C -1 ; WX 608 ; N ugrave ; B 100 -13 642 786 ;
+C -1 ; WX 606 ; N logicalnot ; B 110 109 627 388 ;
+C -1 ; WX 610 ; N ntilde ; B 65 0 609 754 ;
+C -1 ; WX 869 ; N Otilde ; B 105 -13 901 917 ;
+C -1 ; WX 655 ; N otilde ; B 88 -13 669 754 ;
+C -1 ; WX 813 ; N Ccedilla ; B 105 -222 870 752 ;
+C -1 ; WX 740 ; N Agrave ; B 12 0 729 949 ;
+C -1 ; WX 831 ; N onehalf ; B 164 0 810 740 ;
+C -1 ; WX 790 ; N Eth ; B 104 0 813 740 ;
+C -1 ; WX 400 ; N degree ; B 158 421 451 709 ;
+C -1 ; WX 592 ; N Yacute ; B 138 0 729 949 ;
+C -1 ; WX 869 ; N Ocircumflex ; B 105 -13 901 927 ;
+C -1 ; WX 655 ; N oacute ; B 88 -13 669 786 ;
+C -1 ; WX 608 ; N mu ; B 46 -184 628 547 ;
+C -1 ; WX 606 ; N minus ; B 92 219 608 287 ;
+C -1 ; WX 655 ; N eth ; B 88 -12 675 753 ;
+C -1 ; WX 655 ; N odieresis ; B 88 -13 669 765 ;
+C -1 ; WX 747 ; N copyright ; B 53 -12 830 752 ;
+C -1 ; WX 672 ; N brokenbar ; B 280 -100 510 740 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 216
+
+KPX A y -62
+KPX A w -65
+KPX A v -70
+KPX A u -20
+KPX A quoteright -100
+KPX A quotedblright -100
+KPX A Y -92
+KPX A W -60
+KPX A V -102
+KPX A U -40
+KPX A T -45
+KPX A Q -40
+KPX A O -50
+KPX A G -40
+KPX A C -40
+
+KPX B A -10
+
+KPX C A -40
+
+KPX D period -20
+KPX D comma -20
+KPX D Y -30
+KPX D W -10
+KPX D V -50
+KPX D A -50
+
+KPX F period -160
+KPX F e -20
+KPX F comma -180
+KPX F a -20
+KPX F A -75
+
+KPX G period -20
+KPX G comma -20
+KPX G Y -20
+
+KPX J period -15
+KPX J a -20
+KPX J A -30
+
+KPX K o -15
+KPX K e -20
+KPX K O -20
+
+KPX L y -23
+KPX L quoteright -130
+KPX L quotedblright -130
+KPX L Y -91
+KPX L W -67
+KPX L V -113
+KPX L T -46
+
+KPX O period -30
+KPX O comma -30
+KPX O Y -30
+KPX O X -30
+KPX O W -20
+KPX O V -60
+KPX O T -30
+KPX O A -60
+
+KPX P period -300
+KPX P o -60
+KPX P e -20
+KPX P comma -280
+KPX P a -20
+KPX P A -114
+
+KPX Q comma 20
+
+KPX R Y -10
+KPX R W 10
+KPX R V -10
+KPX R T 6
+
+KPX S comma 20
+
+KPX T y -50
+KPX T w -55
+KPX T u -46
+KPX T semicolon -29
+KPX T r -30
+KPX T period -91
+KPX T o -70
+KPX T i 10
+KPX T hyphen -75
+KPX T e -49
+KPX T comma -82
+KPX T colon -15
+KPX T a -90
+KPX T O -30
+KPX T A -45
+
+KPX U period -20
+KPX U comma -20
+KPX U A -40
+
+KPX V u -40
+KPX V semicolon -33
+KPX V period -165
+KPX V o -101
+KPX V i -5
+KPX V hyphen -75
+KPX V e -101
+KPX V comma -145
+KPX V colon -18
+KPX V a -104
+KPX V O -60
+KPX V G -20
+KPX V A -102
+
+KPX W y -2
+KPX W u -30
+KPX W semicolon -33
+KPX W period -106
+KPX W o -46
+KPX W i 6
+KPX W hyphen -35
+KPX W e -47
+KPX W comma -106
+KPX W colon -15
+KPX W a -50
+KPX W O -20
+KPX W A -58
+
+KPX Y u -52
+KPX Y semicolon -23
+KPX Y period -175
+KPX Y o -89
+KPX Y hyphen -85
+KPX Y e -89
+KPX Y comma -145
+KPX Y colon -10
+KPX Y a -93
+KPX Y O -30
+KPX Y A -92
+
+KPX a p 20
+KPX a b 20
+
+KPX b y -20
+KPX b v -20
+
+KPX c y -20
+KPX c k -15
+
+KPX comma space -110
+KPX comma quoteright -120
+KPX comma quotedblright -120
+
+KPX e y -20
+KPX e w -20
+KPX e v -20
+
+KPX f period -50
+KPX f o -40
+KPX f l -30
+KPX f i -34
+KPX f f -60
+KPX f e -20
+KPX f dotlessi -34
+KPX f comma -50
+KPX f a -40
+
+KPX g a -15
+
+KPX h y -30
+
+KPX k y -5
+KPX k e -15
+
+KPX m y -20
+KPX m u -20
+KPX m a -20
+
+KPX n y -15
+KPX n v -20
+
+KPX o y -20
+KPX o x -15
+KPX o w -20
+KPX o v -30
+
+KPX p y -20
+
+KPX period space -110
+KPX period quoteright -120
+KPX period quotedblright -120
+
+KPX quotedblleft quoteleft -35
+KPX quotedblleft A -100
+
+KPX quotedblright space -110
+
+KPX quoteleft quoteleft -203
+KPX quoteleft A -100
+
+KPX quoteright v -30
+KPX quoteright t 10
+KPX quoteright space -110
+KPX quoteright s -15
+KPX quoteright r -20
+KPX quoteright quoteright -203
+KPX quoteright quotedblright -35
+KPX quoteright d -110
+
+KPX r y 40
+KPX r v 40
+KPX r u 20
+KPX r t 20
+KPX r s 20
+KPX r q -8
+KPX r period -73
+KPX r p 20
+KPX r o -20
+KPX r n 21
+KPX r m 28
+KPX r l 20
+KPX r k 20
+KPX r i 20
+KPX r hyphen -60
+KPX r g -15
+KPX r e -4
+KPX r d -6
+KPX r comma -75
+KPX r c -20
+KPX r a -20
+
+KPX s period 20
+KPX s comma 20
+
+KPX space quoteleft -110
+KPX space quotedblleft -110
+KPX space Y -60
+KPX space W -25
+KPX space V -50
+KPX space T -25
+KPX space A -20
+
+KPX v period -130
+KPX v o -30
+KPX v e -20
+KPX v comma -100
+KPX v a -30
+
+KPX w period -100
+KPX w o -30
+KPX w h 15
+KPX w e -20
+KPX w comma -90
+KPX w a -30
+
+KPX y period -125
+KPX y o -30
+KPX y e -20
+KPX y comma -110
+KPX y a -30
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 213 163 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 149 163 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 216 163 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 211 163 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 231 148 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 181 163 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 111 163 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 47 163 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 114 163 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 109 163 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -4 163 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -108 163 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -41 163 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -86 163 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 181 163 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 277 163 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 214 163 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 280 163 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 276 163 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 245 163 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 28 163 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 190 163 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 107 163 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 173 163 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 149 163 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 159 163 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 142 163 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 19 163 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 154 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 91 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 157 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 153 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 176 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 122 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 138 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 74 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 141 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 136 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -47 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -151 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -84 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -129 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 86 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 140 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 77 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 143 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 108 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron -57 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 137 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 53 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 120 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 95 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 101 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron -38 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/AvantGarde-Demi.afm b/tlt3.0/library/afm/AvantGarde-Demi.afm
new file mode 100644
index 0000000..6f96912
--- /dev/null
+++ b/tlt3.0/library/afm/AvantGarde-Demi.afm
@@ -0,0 +1,577 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Mar 4 13:46:34 1991
+Comment UniqueID 34370
+Comment VMusage 24954 31846
+FontName AvantGarde-Demi
+FullName ITC Avant Garde Gothic Demi
+FamilyName ITC Avant Garde Gothic
+Weight Demi
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -123 -251 1222 1021
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.ITC Avant Garde Gothic is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 740
+XHeight 555
+Ascender 740
+Descender -185
+StartCharMetrics 228
+C 32 ; WX 280 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 280 ; N exclam ; B 73 0 206 740 ;
+C 34 ; WX 360 ; N quotedbl ; B 19 444 341 740 ;
+C 35 ; WX 560 ; N numbersign ; B 29 0 525 700 ;
+C 36 ; WX 560 ; N dollar ; B 58 -86 501 857 ;
+C 37 ; WX 860 ; N percent ; B 36 -15 822 755 ;
+C 38 ; WX 680 ; N ampersand ; B 34 -15 665 755 ;
+C 39 ; WX 280 ; N quoteright ; B 72 466 205 740 ;
+C 40 ; WX 380 ; N parenleft ; B 74 -157 350 754 ;
+C 41 ; WX 380 ; N parenright ; B 37 -157 313 754 ;
+C 42 ; WX 440 ; N asterisk ; B 67 457 374 755 ;
+C 43 ; WX 600 ; N plus ; B 48 0 552 506 ;
+C 44 ; WX 280 ; N comma ; B 73 -141 206 133 ;
+C 45 ; WX 420 ; N hyphen ; B 71 230 349 348 ;
+C 46 ; WX 280 ; N period ; B 73 0 206 133 ;
+C 47 ; WX 460 ; N slash ; B 6 -100 454 740 ;
+C 48 ; WX 560 ; N zero ; B 32 -15 529 755 ;
+C 49 ; WX 560 ; N one ; B 137 0 363 740 ;
+C 50 ; WX 560 ; N two ; B 36 0 523 755 ;
+C 51 ; WX 560 ; N three ; B 28 -15 532 755 ;
+C 52 ; WX 560 ; N four ; B 15 0 545 740 ;
+C 53 ; WX 560 ; N five ; B 25 -15 535 740 ;
+C 54 ; WX 560 ; N six ; B 23 -15 536 739 ;
+C 55 ; WX 560 ; N seven ; B 62 0 498 740 ;
+C 56 ; WX 560 ; N eight ; B 33 -15 527 755 ;
+C 57 ; WX 560 ; N nine ; B 24 0 537 754 ;
+C 58 ; WX 280 ; N colon ; B 73 0 206 555 ;
+C 59 ; WX 280 ; N semicolon ; B 73 -141 206 555 ;
+C 60 ; WX 600 ; N less ; B 46 -8 554 514 ;
+C 61 ; WX 600 ; N equal ; B 48 81 552 425 ;
+C 62 ; WX 600 ; N greater ; B 46 -8 554 514 ;
+C 63 ; WX 560 ; N question ; B 38 0 491 755 ;
+C 64 ; WX 740 ; N at ; B 50 -12 750 712 ;
+C 65 ; WX 740 ; N A ; B 7 0 732 740 ;
+C 66 ; WX 580 ; N B ; B 70 0 551 740 ;
+C 67 ; WX 780 ; N C ; B 34 -15 766 755 ;
+C 68 ; WX 700 ; N D ; B 63 0 657 740 ;
+C 69 ; WX 520 ; N E ; B 61 0 459 740 ;
+C 70 ; WX 480 ; N F ; B 61 0 438 740 ;
+C 71 ; WX 840 ; N G ; B 27 -15 817 755 ;
+C 72 ; WX 680 ; N H ; B 71 0 610 740 ;
+C 73 ; WX 280 ; N I ; B 72 0 209 740 ;
+C 74 ; WX 480 ; N J ; B 2 -15 409 740 ;
+C 75 ; WX 620 ; N K ; B 89 0 620 740 ;
+C 76 ; WX 440 ; N L ; B 72 0 435 740 ;
+C 77 ; WX 900 ; N M ; B 63 0 837 740 ;
+C 78 ; WX 740 ; N N ; B 70 0 671 740 ;
+C 79 ; WX 840 ; N O ; B 33 -15 807 755 ;
+C 80 ; WX 560 ; N P ; B 72 0 545 740 ;
+C 81 ; WX 840 ; N Q ; B 32 -15 824 755 ;
+C 82 ; WX 580 ; N R ; B 64 0 565 740 ;
+C 83 ; WX 520 ; N S ; B 12 -15 493 755 ;
+C 84 ; WX 420 ; N T ; B 6 0 418 740 ;
+C 85 ; WX 640 ; N U ; B 55 -15 585 740 ;
+C 86 ; WX 700 ; N V ; B 8 0 695 740 ;
+C 87 ; WX 900 ; N W ; B 7 0 899 740 ;
+C 88 ; WX 680 ; N X ; B 4 0 676 740 ;
+C 89 ; WX 620 ; N Y ; B -2 0 622 740 ;
+C 90 ; WX 500 ; N Z ; B 19 0 481 740 ;
+C 91 ; WX 320 ; N bracketleft ; B 66 -157 284 754 ;
+C 92 ; WX 640 ; N backslash ; B 96 -100 544 740 ;
+C 93 ; WX 320 ; N bracketright ; B 36 -157 254 754 ;
+C 94 ; WX 600 ; N asciicircum ; B 73 375 527 740 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 280 ; N quoteleft ; B 72 466 205 740 ;
+C 97 ; WX 660 ; N a ; B 27 -18 613 574 ;
+C 98 ; WX 660 ; N b ; B 47 -18 632 740 ;
+C 99 ; WX 640 ; N c ; B 37 -18 610 574 ;
+C 100 ; WX 660 ; N d ; B 34 -18 618 740 ;
+C 101 ; WX 640 ; N e ; B 31 -18 610 577 ;
+C 102 ; WX 280 ; N f ; B 15 0 280 755 ; L i fi ; L l fl ;
+C 103 ; WX 660 ; N g ; B 32 -226 623 574 ;
+C 104 ; WX 600 ; N h ; B 54 0 546 740 ;
+C 105 ; WX 240 ; N i ; B 53 0 186 740 ;
+C 106 ; WX 260 ; N j ; B 16 -185 205 740 ;
+C 107 ; WX 580 ; N k ; B 80 0 571 740 ;
+C 108 ; WX 240 ; N l ; B 54 0 187 740 ;
+C 109 ; WX 940 ; N m ; B 54 0 887 574 ;
+C 110 ; WX 600 ; N n ; B 54 0 547 574 ;
+C 111 ; WX 640 ; N o ; B 25 -18 615 574 ;
+C 112 ; WX 660 ; N p ; B 47 -185 629 574 ;
+C 113 ; WX 660 ; N q ; B 31 -185 613 574 ;
+C 114 ; WX 320 ; N r ; B 63 0 317 574 ;
+C 115 ; WX 440 ; N s ; B 19 -18 421 574 ;
+C 116 ; WX 300 ; N t ; B 21 0 299 740 ;
+C 117 ; WX 600 ; N u ; B 50 -18 544 555 ;
+C 118 ; WX 560 ; N v ; B 3 0 556 555 ;
+C 119 ; WX 800 ; N w ; B 11 0 789 555 ;
+C 120 ; WX 560 ; N x ; B 3 0 556 555 ;
+C 121 ; WX 580 ; N y ; B 8 -185 571 555 ;
+C 122 ; WX 460 ; N z ; B 20 0 442 555 ;
+C 123 ; WX 340 ; N braceleft ; B -3 -191 317 747 ;
+C 124 ; WX 600 ; N bar ; B 233 -100 366 740 ;
+C 125 ; WX 340 ; N braceright ; B 23 -191 343 747 ;
+C 126 ; WX 600 ; N asciitilde ; B 67 160 533 347 ;
+C 161 ; WX 280 ; N exclamdown ; B 74 -185 207 555 ;
+C 162 ; WX 560 ; N cent ; B 43 39 517 715 ;
+C 163 ; WX 560 ; N sterling ; B -2 0 562 755 ;
+C 164 ; WX 160 ; N fraction ; B -123 0 282 740 ;
+C 165 ; WX 560 ; N yen ; B -10 0 570 740 ;
+C 166 ; WX 560 ; N florin ; B 0 -151 512 824 ;
+C 167 ; WX 560 ; N section ; B 28 -158 530 755 ;
+C 168 ; WX 560 ; N currency ; B 27 69 534 577 ;
+C 169 ; WX 220 ; N quotesingle ; B 44 444 177 740 ;
+C 170 ; WX 480 ; N quotedblleft ; B 70 466 410 740 ;
+C 171 ; WX 460 ; N guillemotleft ; B 61 108 400 469 ;
+C 172 ; WX 240 ; N guilsinglleft ; B 50 108 190 469 ;
+C 173 ; WX 240 ; N guilsinglright ; B 50 108 190 469 ;
+C 174 ; WX 520 ; N fi ; B 25 0 461 755 ;
+C 175 ; WX 520 ; N fl ; B 25 0 461 755 ;
+C 177 ; WX 500 ; N endash ; B 35 230 465 348 ;
+C 178 ; WX 560 ; N dagger ; B 51 -142 509 740 ;
+C 179 ; WX 560 ; N daggerdbl ; B 51 -142 509 740 ;
+C 180 ; WX 280 ; N periodcentered ; B 73 187 206 320 ;
+C 182 ; WX 600 ; N paragraph ; B -7 -103 607 740 ;
+C 183 ; WX 600 ; N bullet ; B 148 222 453 532 ;
+C 184 ; WX 280 ; N quotesinglbase ; B 72 -141 205 133 ;
+C 185 ; WX 480 ; N quotedblbase ; B 70 -141 410 133 ;
+C 186 ; WX 480 ; N quotedblright ; B 70 466 410 740 ;
+C 187 ; WX 460 ; N guillemotright ; B 61 108 400 469 ;
+C 188 ; WX 1000 ; N ellipsis ; B 100 0 899 133 ;
+C 189 ; WX 1280 ; N perthousand ; B 36 -15 1222 755 ;
+C 191 ; WX 560 ; N questiondown ; B 68 -200 521 555 ;
+C 193 ; WX 420 ; N grave ; B 50 624 329 851 ;
+C 194 ; WX 420 ; N acute ; B 91 624 370 849 ;
+C 195 ; WX 540 ; N circumflex ; B 71 636 470 774 ;
+C 196 ; WX 480 ; N tilde ; B 44 636 437 767 ;
+C 197 ; WX 420 ; N macron ; B 72 648 349 759 ;
+C 198 ; WX 480 ; N breve ; B 42 633 439 770 ;
+C 199 ; WX 280 ; N dotaccent ; B 74 636 207 769 ;
+C 200 ; WX 500 ; N dieresis ; B 78 636 422 769 ;
+C 202 ; WX 360 ; N ring ; B 73 619 288 834 ;
+C 203 ; WX 340 ; N cedilla ; B 98 -251 298 6 ;
+C 205 ; WX 700 ; N hungarumlaut ; B 132 610 609 862 ;
+C 206 ; WX 340 ; N ogonek ; B 79 -195 262 9 ;
+C 207 ; WX 540 ; N caron ; B 71 636 470 774 ;
+C 208 ; WX 1000 ; N emdash ; B 35 230 965 348 ;
+C 225 ; WX 900 ; N AE ; B -5 0 824 740 ;
+C 227 ; WX 360 ; N ordfeminine ; B 19 438 334 755 ;
+C 232 ; WX 480 ; N Lslash ; B 26 0 460 740 ;
+C 233 ; WX 840 ; N Oslash ; B 33 -71 807 814 ;
+C 234 ; WX 1060 ; N OE ; B 37 -15 1007 755 ;
+C 235 ; WX 360 ; N ordmasculine ; B 23 438 338 755 ;
+C 241 ; WX 1080 ; N ae ; B 29 -18 1048 574 ;
+C 245 ; WX 240 ; N dotlessi ; B 53 0 186 555 ;
+C 248 ; WX 320 ; N lslash ; B 34 0 305 740 ;
+C 249 ; WX 660 ; N oslash ; B 35 -50 625 608 ;
+C 250 ; WX 1080 ; N oe ; B 30 -18 1050 574 ;
+C 251 ; WX 600 ; N germandbls ; B 51 -18 585 755 ;
+C -1 ; WX 640 ; N ecircumflex ; B 31 -18 610 774 ;
+C -1 ; WX 640 ; N edieresis ; B 31 -18 610 769 ;
+C -1 ; WX 660 ; N aacute ; B 27 -18 613 849 ;
+C -1 ; WX 740 ; N registered ; B -12 -12 752 752 ;
+C -1 ; WX 240 ; N icircumflex ; B -79 0 320 774 ;
+C -1 ; WX 600 ; N udieresis ; B 50 -18 544 769 ;
+C -1 ; WX 640 ; N ograve ; B 25 -18 615 851 ;
+C -1 ; WX 600 ; N uacute ; B 50 -18 544 849 ;
+C -1 ; WX 600 ; N ucircumflex ; B 50 -18 544 774 ;
+C -1 ; WX 740 ; N Aacute ; B 7 0 732 1019 ;
+C -1 ; WX 240 ; N igrave ; B -65 0 214 851 ;
+C -1 ; WX 280 ; N Icircumflex ; B -59 0 340 944 ;
+C -1 ; WX 640 ; N ccedilla ; B 37 -251 610 574 ;
+C -1 ; WX 660 ; N adieresis ; B 27 -18 613 769 ;
+C -1 ; WX 520 ; N Ecircumflex ; B 61 0 460 944 ;
+C -1 ; WX 440 ; N scaron ; B 19 -18 421 774 ;
+C -1 ; WX 660 ; N thorn ; B 47 -185 629 740 ;
+C -1 ; WX 1000 ; N trademark ; B 9 296 821 740 ;
+C -1 ; WX 640 ; N egrave ; B 31 -18 610 851 ;
+C -1 ; WX 336 ; N threesuperior ; B 8 287 328 749 ;
+C -1 ; WX 460 ; N zcaron ; B 20 0 455 774 ;
+C -1 ; WX 660 ; N atilde ; B 27 -18 613 767 ;
+C -1 ; WX 660 ; N aring ; B 27 -18 613 834 ;
+C -1 ; WX 640 ; N ocircumflex ; B 25 -18 615 774 ;
+C -1 ; WX 520 ; N Edieresis ; B 61 0 459 939 ;
+C -1 ; WX 840 ; N threequarters ; B 18 0 803 749 ;
+C -1 ; WX 580 ; N ydieresis ; B 8 -185 571 769 ;
+C -1 ; WX 580 ; N yacute ; B 8 -185 571 849 ;
+C -1 ; WX 240 ; N iacute ; B 26 0 305 849 ;
+C -1 ; WX 740 ; N Acircumflex ; B 7 0 732 944 ;
+C -1 ; WX 640 ; N Uacute ; B 55 -15 585 1019 ;
+C -1 ; WX 640 ; N eacute ; B 31 -18 610 849 ;
+C -1 ; WX 840 ; N Ograve ; B 33 -15 807 1021 ;
+C -1 ; WX 660 ; N agrave ; B 27 -18 613 851 ;
+C -1 ; WX 640 ; N Udieresis ; B 55 -15 585 939 ;
+C -1 ; WX 660 ; N acircumflex ; B 27 -18 613 774 ;
+C -1 ; WX 280 ; N Igrave ; B -45 0 234 1021 ;
+C -1 ; WX 336 ; N twosuperior ; B 13 296 322 749 ;
+C -1 ; WX 640 ; N Ugrave ; B 55 -15 585 1021 ;
+C -1 ; WX 840 ; N onequarter ; B 92 0 746 740 ;
+C -1 ; WX 640 ; N Ucircumflex ; B 55 -15 585 944 ;
+C -1 ; WX 520 ; N Scaron ; B 12 -15 493 944 ;
+C -1 ; WX 280 ; N Idieresis ; B -32 0 312 939 ;
+C -1 ; WX 240 ; N idieresis ; B -52 0 292 769 ;
+C -1 ; WX 520 ; N Egrave ; B 61 0 459 1021 ;
+C -1 ; WX 840 ; N Oacute ; B 33 -15 807 1019 ;
+C -1 ; WX 600 ; N divide ; B 48 -20 552 526 ;
+C -1 ; WX 740 ; N Atilde ; B 7 0 732 937 ;
+C -1 ; WX 740 ; N Aring ; B 7 0 732 969 ;
+C -1 ; WX 840 ; N Odieresis ; B 33 -15 807 939 ;
+C -1 ; WX 740 ; N Adieresis ; B 7 0 732 939 ;
+C -1 ; WX 740 ; N Ntilde ; B 70 0 671 937 ;
+C -1 ; WX 500 ; N Zcaron ; B 19 0 481 944 ;
+C -1 ; WX 560 ; N Thorn ; B 72 0 545 740 ;
+C -1 ; WX 280 ; N Iacute ; B 46 0 325 1019 ;
+C -1 ; WX 600 ; N plusminus ; B 48 -62 552 556 ;
+C -1 ; WX 600 ; N multiply ; B 59 12 541 494 ;
+C -1 ; WX 520 ; N Eacute ; B 61 0 459 1019 ;
+C -1 ; WX 620 ; N Ydieresis ; B -2 0 622 939 ;
+C -1 ; WX 336 ; N onesuperior ; B 72 296 223 740 ;
+C -1 ; WX 600 ; N ugrave ; B 50 -18 544 851 ;
+C -1 ; WX 600 ; N logicalnot ; B 48 108 552 425 ;
+C -1 ; WX 600 ; N ntilde ; B 54 0 547 767 ;
+C -1 ; WX 840 ; N Otilde ; B 33 -15 807 937 ;
+C -1 ; WX 640 ; N otilde ; B 25 -18 615 767 ;
+C -1 ; WX 780 ; N Ccedilla ; B 34 -251 766 755 ;
+C -1 ; WX 740 ; N Agrave ; B 7 0 732 1021 ;
+C -1 ; WX 840 ; N onehalf ; B 62 0 771 740 ;
+C -1 ; WX 742 ; N Eth ; B 25 0 691 740 ;
+C -1 ; WX 400 ; N degree ; B 57 426 343 712 ;
+C -1 ; WX 620 ; N Yacute ; B -2 0 622 1019 ;
+C -1 ; WX 840 ; N Ocircumflex ; B 33 -15 807 944 ;
+C -1 ; WX 640 ; N oacute ; B 25 -18 615 849 ;
+C -1 ; WX 576 ; N mu ; B 38 -187 539 555 ;
+C -1 ; WX 600 ; N minus ; B 48 193 552 313 ;
+C -1 ; WX 640 ; N eth ; B 27 -18 616 754 ;
+C -1 ; WX 640 ; N odieresis ; B 25 -18 615 769 ;
+C -1 ; WX 740 ; N copyright ; B -12 -12 752 752 ;
+C -1 ; WX 600 ; N brokenbar ; B 233 -100 366 740 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 218
+
+KPX A y -50
+KPX A w -65
+KPX A v -70
+KPX A u -20
+KPX A quoteright -90
+KPX A Y -80
+KPX A W -60
+KPX A V -102
+KPX A U -40
+KPX A T -25
+KPX A Q -50
+KPX A O -50
+KPX A G -40
+KPX A C -40
+
+KPX B A -10
+
+KPX C A -40
+
+KPX D period -20
+KPX D comma -20
+KPX D Y -45
+KPX D W -25
+KPX D V -50
+KPX D A -50
+
+KPX F period -129
+KPX F e -20
+KPX F comma -162
+KPX F a -20
+KPX F A -75
+
+KPX G period -20
+KPX G comma -20
+KPX G Y -15
+
+KPX J period -15
+KPX J a -20
+KPX J A -30
+
+KPX K y -20
+KPX K u -15
+KPX K o -45
+KPX K e -40
+KPX K O -30
+
+KPX L y -23
+KPX L quoteright -30
+KPX L quotedblright -30
+KPX L Y -80
+KPX L W -55
+KPX L V -85
+KPX L T -46
+
+KPX O period -30
+KPX O comma -30
+KPX O Y -30
+KPX O X -30
+KPX O W -20
+KPX O V -45
+KPX O T -15
+KPX O A -60
+
+KPX P period -200
+KPX P o -20
+KPX P e -20
+KPX P comma -220
+KPX P a -20
+KPX P A -100
+
+KPX Q comma 20
+
+KPX R W 25
+KPX R V -10
+KPX R U 25
+KPX R T 40
+KPX R O 25
+
+KPX S comma 20
+
+KPX T y -10
+KPX T w -55
+KPX T u -46
+KPX T semicolon -29
+KPX T r -30
+KPX T period -91
+KPX T o -49
+KPX T hyphen -75
+KPX T e -49
+KPX T comma -82
+KPX T colon -15
+KPX T a -70
+KPX T O -15
+KPX T A -25
+
+KPX U period -20
+KPX U comma -20
+KPX U A -40
+
+KPX V u -55
+KPX V semicolon -33
+KPX V period -145
+KPX V o -101
+KPX V i -15
+KPX V hyphen -75
+KPX V e -101
+KPX V comma -145
+KPX V colon -18
+KPX V a -95
+KPX V O -45
+KPX V G -20
+KPX V A -102
+
+KPX W y -15
+KPX W u -30
+KPX W semicolon -33
+KPX W period -106
+KPX W o -46
+KPX W i -10
+KPX W hyphen -35
+KPX W e -47
+KPX W comma -106
+KPX W colon -15
+KPX W a -50
+KPX W O -20
+KPX W A -58
+
+KPX Y u -52
+KPX Y semicolon -23
+KPX Y period -145
+KPX Y o -89
+KPX Y hyphen -100
+KPX Y e -89
+KPX Y comma -145
+KPX Y colon -10
+KPX Y a -93
+KPX Y O -30
+KPX Y A -80
+
+KPX a t 5
+KPX a p 20
+KPX a b 5
+
+KPX b y -20
+KPX b v -20
+
+KPX c y -20
+KPX c l -15
+KPX c k -15
+
+KPX comma space -50
+KPX comma quoteright -70
+KPX comma quotedblright -70
+
+KPX e y -20
+KPX e x -20
+KPX e w -20
+KPX e v -20
+
+KPX f period -40
+KPX f o -20
+KPX f l -15
+KPX f i -15
+KPX f f -20
+KPX f dotlessi -15
+KPX f comma -40
+KPX f a -15
+
+KPX g i 25
+KPX g a 15
+
+KPX h y -30
+
+KPX k y -5
+KPX k o -30
+KPX k e -40
+
+KPX m y -20
+KPX m u -20
+
+KPX n y -15
+KPX n v -30
+
+KPX o y -20
+KPX o x -30
+KPX o w -20
+KPX o v -30
+
+KPX p y -20
+
+KPX period space -50
+KPX period quoteright -70
+KPX period quotedblright -70
+
+KPX quotedblleft A -50
+
+KPX quotedblright space -50
+
+KPX quoteleft quoteleft -80
+KPX quoteleft A -50
+
+KPX quoteright v -10
+KPX quoteright t 10
+KPX quoteright space -50
+KPX quoteright s -15
+KPX quoteright r -20
+KPX quoteright quoteright -80
+KPX quoteright d -50
+
+KPX r y 40
+KPX r v 40
+KPX r u 20
+KPX r t 20
+KPX r s 20
+KPX r q -8
+KPX r period -73
+KPX r p 20
+KPX r o -15
+KPX r n 21
+KPX r m 15
+KPX r l 20
+KPX r k 5
+KPX r i 20
+KPX r hyphen -60
+KPX r g 1
+KPX r e -4
+KPX r d -6
+KPX r comma -75
+KPX r c -7
+
+KPX s period 20
+KPX s comma 20
+
+KPX space quoteleft -50
+KPX space quotedblleft -50
+KPX space Y -60
+KPX space W -25
+KPX space V -80
+KPX space T -25
+KPX space A -20
+
+KPX v period -90
+KPX v o -20
+KPX v e -20
+KPX v comma -90
+KPX v a -30
+
+KPX w period -90
+KPX w o -30
+KPX w e -20
+KPX w comma -90
+KPX w a -30
+
+KPX x e -20
+
+KPX y period -100
+KPX y o -30
+KPX y e -20
+KPX y comma -100
+KPX y c -35
+KPX y a -30
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 170 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 100 170 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 120 170 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 160 170 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 190 135 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 130 170 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 50 170 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex -10 170 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 10 170 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 50 170 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -45 170 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -130 170 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -110 170 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -95 170 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 130 170 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 210 170 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 150 170 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 170 170 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 210 170 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 180 170 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron -10 170 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 145 170 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 50 170 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 70 170 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 75 170 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 135 170 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 60 170 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 5 170 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 120 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 60 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 80 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 120 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 150 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 90 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 110 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 50 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 70 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 110 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -65 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -150 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -130 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -115 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 60 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 110 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 50 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 70 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 110 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 80 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron -50 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 125 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 30 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 50 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 55 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 115 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 40 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron -15 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/AvantGarde-DemiOblique.afm b/tlt3.0/library/afm/AvantGarde-DemiOblique.afm
new file mode 100644
index 0000000..ea40ef1
--- /dev/null
+++ b/tlt3.0/library/afm/AvantGarde-DemiOblique.afm
@@ -0,0 +1,577 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Mar 4 13:49:44 1991
+Comment UniqueID 34373
+Comment VMusage 6550 39938
+FontName AvantGarde-DemiOblique
+FullName ITC Avant Garde Gothic Demi Oblique
+FamilyName ITC Avant Garde Gothic
+Weight Demi
+ItalicAngle -10.5
+IsFixedPitch false
+FontBBox -123 -251 1256 1021
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990, 1991 Adobe Systems Incorporated. All Rights Reserved.ITC Avant Garde Gothic is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 740
+XHeight 555
+Ascender 740
+Descender -185
+StartCharMetrics 228
+C 32 ; WX 280 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 280 ; N exclam ; B 73 0 343 740 ;
+C 34 ; WX 360 ; N quotedbl ; B 127 444 478 740 ;
+C 35 ; WX 560 ; N numbersign ; B 66 0 618 700 ;
+C 36 ; WX 560 ; N dollar ; B 99 -86 582 857 ;
+C 37 ; WX 860 ; N percent ; B 139 -15 856 755 ;
+C 38 ; WX 680 ; N ampersand ; B 71 -15 742 755 ;
+C 39 ; WX 280 ; N quoteright ; B 159 466 342 740 ;
+C 40 ; WX 380 ; N parenleft ; B 120 -157 490 754 ;
+C 41 ; WX 380 ; N parenright ; B 8 -157 378 754 ;
+C 42 ; WX 440 ; N asterisk ; B 174 457 492 755 ;
+C 43 ; WX 600 ; N plus ; B 84 0 610 506 ;
+C 44 ; WX 280 ; N comma ; B 48 -141 231 133 ;
+C 45 ; WX 420 ; N hyphen ; B 114 230 413 348 ;
+C 46 ; WX 280 ; N period ; B 73 0 231 133 ;
+C 47 ; WX 460 ; N slash ; B -13 -100 591 740 ;
+C 48 ; WX 560 ; N zero ; B 70 -15 628 755 ;
+C 49 ; WX 560 ; N one ; B 230 0 500 740 ;
+C 50 ; WX 560 ; N two ; B 44 0 622 755 ;
+C 51 ; WX 560 ; N three ; B 67 -15 585 755 ;
+C 52 ; WX 560 ; N four ; B 36 0 604 740 ;
+C 53 ; WX 560 ; N five ; B 64 -15 600 740 ;
+C 54 ; WX 560 ; N six ; B 64 -15 587 739 ;
+C 55 ; WX 560 ; N seven ; B 83 0 635 740 ;
+C 56 ; WX 560 ; N eight ; B 71 -15 590 755 ;
+C 57 ; WX 560 ; N nine ; B 110 0 633 754 ;
+C 58 ; WX 280 ; N colon ; B 73 0 309 555 ;
+C 59 ; WX 280 ; N semicolon ; B 48 -141 309 555 ;
+C 60 ; WX 600 ; N less ; B 84 -8 649 514 ;
+C 61 ; WX 600 ; N equal ; B 63 81 631 425 ;
+C 62 ; WX 600 ; N greater ; B 45 -8 610 514 ;
+C 63 ; WX 560 ; N question ; B 135 0 593 755 ;
+C 64 ; WX 740 ; N at ; B 109 -12 832 712 ;
+C 65 ; WX 740 ; N A ; B 7 0 732 740 ;
+C 66 ; WX 580 ; N B ; B 70 0 610 740 ;
+C 67 ; WX 780 ; N C ; B 97 -15 864 755 ;
+C 68 ; WX 700 ; N D ; B 63 0 732 740 ;
+C 69 ; WX 520 ; N E ; B 61 0 596 740 ;
+C 70 ; WX 480 ; N F ; B 61 0 575 740 ;
+C 71 ; WX 840 ; N G ; B 89 -15 887 755 ;
+C 72 ; WX 680 ; N H ; B 71 0 747 740 ;
+C 73 ; WX 280 ; N I ; B 72 0 346 740 ;
+C 74 ; WX 480 ; N J ; B 34 -15 546 740 ;
+C 75 ; WX 620 ; N K ; B 89 0 757 740 ;
+C 76 ; WX 440 ; N L ; B 72 0 459 740 ;
+C 77 ; WX 900 ; N M ; B 63 0 974 740 ;
+C 78 ; WX 740 ; N N ; B 70 0 808 740 ;
+C 79 ; WX 840 ; N O ; B 95 -15 882 755 ;
+C 80 ; WX 560 ; N P ; B 72 0 645 740 ;
+C 81 ; WX 840 ; N Q ; B 94 -15 882 755 ;
+C 82 ; WX 580 ; N R ; B 64 0 656 740 ;
+C 83 ; WX 520 ; N S ; B 49 -15 578 755 ;
+C 84 ; WX 420 ; N T ; B 119 0 555 740 ;
+C 85 ; WX 640 ; N U ; B 97 -15 722 740 ;
+C 86 ; WX 700 ; N V ; B 145 0 832 740 ;
+C 87 ; WX 900 ; N W ; B 144 0 1036 740 ;
+C 88 ; WX 680 ; N X ; B 4 0 813 740 ;
+C 89 ; WX 620 ; N Y ; B 135 0 759 740 ;
+C 90 ; WX 500 ; N Z ; B 19 0 599 740 ;
+C 91 ; WX 320 ; N bracketleft ; B 89 -157 424 754 ;
+C 92 ; WX 640 ; N backslash ; B 233 -100 525 740 ;
+C 93 ; WX 320 ; N bracketright ; B 7 -157 342 754 ;
+C 94 ; WX 600 ; N asciicircum ; B 142 375 596 740 ;
+C 95 ; WX 500 ; N underscore ; B -23 -125 486 -75 ;
+C 96 ; WX 280 ; N quoteleft ; B 158 466 341 740 ;
+C 97 ; WX 660 ; N a ; B 73 -18 716 574 ;
+C 98 ; WX 660 ; N b ; B 47 -18 689 740 ;
+C 99 ; WX 640 ; N c ; B 84 -18 679 574 ;
+C 100 ; WX 660 ; N d ; B 80 -18 755 740 ;
+C 101 ; WX 640 ; N e ; B 77 -18 667 577 ;
+C 102 ; WX 280 ; N f ; B 62 0 420 755 ; L i fi ; L l fl ;
+C 103 ; WX 660 ; N g ; B 33 -226 726 574 ;
+C 104 ; WX 600 ; N h ; B 54 0 614 740 ;
+C 105 ; WX 240 ; N i ; B 53 0 323 740 ;
+C 106 ; WX 260 ; N j ; B -18 -185 342 740 ;
+C 107 ; WX 580 ; N k ; B 80 0 648 740 ;
+C 108 ; WX 240 ; N l ; B 54 0 324 740 ;
+C 109 ; WX 940 ; N m ; B 54 0 954 574 ;
+C 110 ; WX 600 ; N n ; B 54 0 613 574 ;
+C 111 ; WX 640 ; N o ; B 71 -18 672 574 ;
+C 112 ; WX 660 ; N p ; B 13 -185 686 574 ;
+C 113 ; WX 660 ; N q ; B 78 -185 716 574 ;
+C 114 ; WX 320 ; N r ; B 63 0 423 574 ;
+C 115 ; WX 440 ; N s ; B 49 -18 483 574 ;
+C 116 ; WX 300 ; N t ; B 86 0 402 740 ;
+C 117 ; WX 600 ; N u ; B 87 -18 647 555 ;
+C 118 ; WX 560 ; N v ; B 106 0 659 555 ;
+C 119 ; WX 800 ; N w ; B 114 0 892 555 ;
+C 120 ; WX 560 ; N x ; B 3 0 632 555 ;
+C 121 ; WX 580 ; N y ; B 75 -185 674 555 ;
+C 122 ; WX 460 ; N z ; B 20 0 528 555 ;
+C 123 ; WX 340 ; N braceleft ; B 40 -191 455 747 ;
+C 124 ; WX 600 ; N bar ; B 214 -100 503 740 ;
+C 125 ; WX 340 ; N braceright ; B -12 -191 405 747 ;
+C 126 ; WX 600 ; N asciitilde ; B 114 160 579 347 ;
+C 161 ; WX 280 ; N exclamdown ; B 40 -185 310 555 ;
+C 162 ; WX 560 ; N cent ; B 110 39 599 715 ;
+C 163 ; WX 560 ; N sterling ; B 38 0 615 755 ;
+C 164 ; WX 160 ; N fraction ; B -123 0 419 740 ;
+C 165 ; WX 560 ; N yen ; B 83 0 707 740 ;
+C 166 ; WX 560 ; N florin ; B -27 -151 664 824 ;
+C 167 ; WX 560 ; N section ; B 65 -158 602 755 ;
+C 168 ; WX 560 ; N currency ; B 53 69 628 577 ;
+C 169 ; WX 220 ; N quotesingle ; B 152 444 314 740 ;
+C 170 ; WX 480 ; N quotedblleft ; B 156 466 546 740 ;
+C 171 ; WX 460 ; N guillemotleft ; B 105 108 487 469 ;
+C 172 ; WX 240 ; N guilsinglleft ; B 94 108 277 469 ;
+C 173 ; WX 240 ; N guilsinglright ; B 70 108 253 469 ;
+C 174 ; WX 520 ; N fi ; B 72 0 598 755 ;
+C 175 ; WX 520 ; N fl ; B 72 0 598 755 ;
+C 177 ; WX 500 ; N endash ; B 78 230 529 348 ;
+C 178 ; WX 560 ; N dagger ; B 133 -142 612 740 ;
+C 179 ; WX 560 ; N daggerdbl ; B 63 -142 618 740 ;
+C 180 ; WX 280 ; N periodcentered ; B 108 187 265 320 ;
+C 182 ; WX 600 ; N paragraph ; B 90 -103 744 740 ;
+C 183 ; WX 600 ; N bullet ; B 215 222 526 532 ;
+C 184 ; WX 280 ; N quotesinglbase ; B 47 -141 230 133 ;
+C 185 ; WX 480 ; N quotedblbase ; B 45 -141 435 133 ;
+C 186 ; WX 480 ; N quotedblright ; B 157 466 547 740 ;
+C 187 ; WX 460 ; N guillemotright ; B 81 108 463 469 ;
+C 188 ; WX 1000 ; N ellipsis ; B 100 0 924 133 ;
+C 189 ; WX 1280 ; N perthousand ; B 139 -15 1256 755 ;
+C 191 ; WX 560 ; N questiondown ; B 69 -200 527 555 ;
+C 193 ; WX 420 ; N grave ; B 189 624 462 851 ;
+C 194 ; WX 420 ; N acute ; B 224 624 508 849 ;
+C 195 ; WX 540 ; N circumflex ; B 189 636 588 774 ;
+C 196 ; WX 480 ; N tilde ; B 178 636 564 767 ;
+C 197 ; WX 420 ; N macron ; B 192 648 490 759 ;
+C 198 ; WX 480 ; N breve ; B 185 633 582 770 ;
+C 199 ; WX 280 ; N dotaccent ; B 192 636 350 769 ;
+C 200 ; WX 500 ; N dieresis ; B 196 636 565 769 ;
+C 202 ; WX 360 ; N ring ; B 206 619 424 834 ;
+C 203 ; WX 340 ; N cedilla ; B 67 -251 272 6 ;
+C 205 ; WX 700 ; N hungarumlaut ; B 258 610 754 862 ;
+C 206 ; WX 340 ; N ogonek ; B 59 -195 243 9 ;
+C 207 ; WX 540 ; N caron ; B 214 636 613 774 ;
+C 208 ; WX 1000 ; N emdash ; B 78 230 1029 348 ;
+C 225 ; WX 900 ; N AE ; B -5 0 961 740 ;
+C 227 ; WX 360 ; N ordfeminine ; B 127 438 472 755 ;
+C 232 ; WX 480 ; N Lslash ; B 68 0 484 740 ;
+C 233 ; WX 840 ; N Oslash ; B 94 -71 891 814 ;
+C 234 ; WX 1060 ; N OE ; B 98 -15 1144 755 ;
+C 235 ; WX 360 ; N ordmasculine ; B 131 438 451 755 ;
+C 241 ; WX 1080 ; N ae ; B 75 -18 1105 574 ;
+C 245 ; WX 240 ; N dotlessi ; B 53 0 289 555 ;
+C 248 ; WX 320 ; N lslash ; B 74 0 404 740 ;
+C 249 ; WX 660 ; N oslash ; B 81 -50 685 608 ;
+C 250 ; WX 1080 ; N oe ; B 76 -18 1108 574 ;
+C 251 ; WX 600 ; N germandbls ; B 51 -18 629 755 ;
+C -1 ; WX 640 ; N ecircumflex ; B 77 -18 667 774 ;
+C -1 ; WX 640 ; N edieresis ; B 77 -18 667 769 ;
+C -1 ; WX 660 ; N aacute ; B 73 -18 716 849 ;
+C -1 ; WX 740 ; N registered ; B 50 -12 827 752 ;
+C -1 ; WX 240 ; N icircumflex ; B 39 0 438 774 ;
+C -1 ; WX 600 ; N udieresis ; B 87 -18 647 769 ;
+C -1 ; WX 640 ; N ograve ; B 71 -18 672 851 ;
+C -1 ; WX 600 ; N uacute ; B 87 -18 647 849 ;
+C -1 ; WX 600 ; N ucircumflex ; B 87 -18 647 774 ;
+C -1 ; WX 740 ; N Aacute ; B 7 0 732 1019 ;
+C -1 ; WX 240 ; N igrave ; B 53 0 347 851 ;
+C -1 ; WX 280 ; N Icircumflex ; B 72 0 489 944 ;
+C -1 ; WX 640 ; N ccedilla ; B 83 -251 679 574 ;
+C -1 ; WX 660 ; N adieresis ; B 73 -18 716 769 ;
+C -1 ; WX 520 ; N Ecircumflex ; B 61 0 609 944 ;
+C -1 ; WX 440 ; N scaron ; B 49 -18 563 774 ;
+C -1 ; WX 660 ; N thorn ; B 13 -185 686 740 ;
+C -1 ; WX 1000 ; N trademark ; B 131 296 958 740 ;
+C -1 ; WX 640 ; N egrave ; B 77 -18 667 851 ;
+C -1 ; WX 336 ; N threesuperior ; B 87 287 413 749 ;
+C -1 ; WX 460 ; N zcaron ; B 20 0 598 774 ;
+C -1 ; WX 660 ; N atilde ; B 73 -18 716 767 ;
+C -1 ; WX 660 ; N aring ; B 73 -18 716 834 ;
+C -1 ; WX 640 ; N ocircumflex ; B 71 -18 672 774 ;
+C -1 ; WX 520 ; N Edieresis ; B 61 0 606 939 ;
+C -1 ; WX 840 ; N threequarters ; B 97 0 836 749 ;
+C -1 ; WX 580 ; N ydieresis ; B 75 -185 674 769 ;
+C -1 ; WX 580 ; N yacute ; B 75 -185 674 849 ;
+C -1 ; WX 240 ; N iacute ; B 53 0 443 849 ;
+C -1 ; WX 740 ; N Acircumflex ; B 7 0 732 944 ;
+C -1 ; WX 640 ; N Uacute ; B 97 -15 722 1019 ;
+C -1 ; WX 640 ; N eacute ; B 77 -18 667 849 ;
+C -1 ; WX 840 ; N Ograve ; B 95 -15 882 1021 ;
+C -1 ; WX 660 ; N agrave ; B 73 -18 716 851 ;
+C -1 ; WX 640 ; N Udieresis ; B 97 -15 722 939 ;
+C -1 ; WX 660 ; N acircumflex ; B 73 -18 716 774 ;
+C -1 ; WX 280 ; N Igrave ; B 72 0 398 1021 ;
+C -1 ; WX 336 ; N twosuperior ; B 73 296 436 749 ;
+C -1 ; WX 640 ; N Ugrave ; B 97 -15 722 1021 ;
+C -1 ; WX 840 ; N onequarter ; B 187 0 779 740 ;
+C -1 ; WX 640 ; N Ucircumflex ; B 97 -15 722 944 ;
+C -1 ; WX 520 ; N Scaron ; B 49 -15 635 944 ;
+C -1 ; WX 280 ; N Idieresis ; B 72 0 486 939 ;
+C -1 ; WX 240 ; N idieresis ; B 53 0 435 769 ;
+C -1 ; WX 520 ; N Egrave ; B 61 0 596 1021 ;
+C -1 ; WX 840 ; N Oacute ; B 95 -15 882 1019 ;
+C -1 ; WX 600 ; N divide ; B 84 -20 610 526 ;
+C -1 ; WX 740 ; N Atilde ; B 7 0 732 937 ;
+C -1 ; WX 740 ; N Aring ; B 7 0 732 969 ;
+C -1 ; WX 840 ; N Odieresis ; B 95 -15 882 939 ;
+C -1 ; WX 740 ; N Adieresis ; B 7 0 732 939 ;
+C -1 ; WX 740 ; N Ntilde ; B 70 0 808 937 ;
+C -1 ; WX 500 ; N Zcaron ; B 19 0 650 944 ;
+C -1 ; WX 560 ; N Thorn ; B 72 0 619 740 ;
+C -1 ; WX 280 ; N Iacute ; B 72 0 494 1019 ;
+C -1 ; WX 600 ; N plusminus ; B 37 -62 626 556 ;
+C -1 ; WX 600 ; N multiply ; B 76 12 617 494 ;
+C -1 ; WX 520 ; N Eacute ; B 61 0 596 1019 ;
+C -1 ; WX 620 ; N Ydieresis ; B 135 0 759 939 ;
+C -1 ; WX 336 ; N onesuperior ; B 182 296 360 740 ;
+C -1 ; WX 600 ; N ugrave ; B 87 -18 647 851 ;
+C -1 ; WX 600 ; N logicalnot ; B 105 108 631 425 ;
+C -1 ; WX 600 ; N ntilde ; B 54 0 624 767 ;
+C -1 ; WX 840 ; N Otilde ; B 95 -15 882 937 ;
+C -1 ; WX 640 ; N otilde ; B 71 -18 672 767 ;
+C -1 ; WX 780 ; N Ccedilla ; B 97 -251 864 755 ;
+C -1 ; WX 740 ; N Agrave ; B 7 0 732 1021 ;
+C -1 ; WX 840 ; N onehalf ; B 157 0 830 740 ;
+C -1 ; WX 742 ; N Eth ; B 83 0 766 740 ;
+C -1 ; WX 400 ; N degree ; B 160 426 451 712 ;
+C -1 ; WX 620 ; N Yacute ; B 135 0 759 1019 ;
+C -1 ; WX 840 ; N Ocircumflex ; B 95 -15 882 944 ;
+C -1 ; WX 640 ; N oacute ; B 71 -18 672 849 ;
+C -1 ; WX 576 ; N mu ; B 3 -187 642 555 ;
+C -1 ; WX 600 ; N minus ; B 84 193 610 313 ;
+C -1 ; WX 640 ; N eth ; B 73 -18 699 754 ;
+C -1 ; WX 640 ; N odieresis ; B 71 -18 672 769 ;
+C -1 ; WX 740 ; N copyright ; B 50 -12 827 752 ;
+C -1 ; WX 600 ; N brokenbar ; B 214 -100 503 740 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 218
+
+KPX A y -50
+KPX A w -65
+KPX A v -70
+KPX A u -20
+KPX A quoteright -90
+KPX A Y -80
+KPX A W -60
+KPX A V -102
+KPX A U -40
+KPX A T -25
+KPX A Q -50
+KPX A O -50
+KPX A G -40
+KPX A C -40
+
+KPX B A -10
+
+KPX C A -40
+
+KPX D period -20
+KPX D comma -20
+KPX D Y -45
+KPX D W -25
+KPX D V -50
+KPX D A -50
+
+KPX F period -129
+KPX F e -20
+KPX F comma -162
+KPX F a -20
+KPX F A -75
+
+KPX G period -20
+KPX G comma -20
+KPX G Y -15
+
+KPX J period -15
+KPX J a -20
+KPX J A -30
+
+KPX K y -20
+KPX K u -15
+KPX K o -45
+KPX K e -40
+KPX K O -30
+
+KPX L y -23
+KPX L quoteright -30
+KPX L quotedblright -30
+KPX L Y -80
+KPX L W -55
+KPX L V -85
+KPX L T -46
+
+KPX O period -30
+KPX O comma -30
+KPX O Y -30
+KPX O X -30
+KPX O W -20
+KPX O V -45
+KPX O T -15
+KPX O A -60
+
+KPX P period -200
+KPX P o -20
+KPX P e -20
+KPX P comma -220
+KPX P a -20
+KPX P A -100
+
+KPX Q comma 20
+
+KPX R W 25
+KPX R V -10
+KPX R U 25
+KPX R T 40
+KPX R O 25
+
+KPX S comma 20
+
+KPX T y -10
+KPX T w -55
+KPX T u -46
+KPX T semicolon -29
+KPX T r -30
+KPX T period -91
+KPX T o -49
+KPX T hyphen -75
+KPX T e -49
+KPX T comma -82
+KPX T colon -15
+KPX T a -70
+KPX T O -15
+KPX T A -25
+
+KPX U period -20
+KPX U comma -20
+KPX U A -40
+
+KPX V u -55
+KPX V semicolon -33
+KPX V period -145
+KPX V o -101
+KPX V i -15
+KPX V hyphen -75
+KPX V e -101
+KPX V comma -145
+KPX V colon -18
+KPX V a -95
+KPX V O -45
+KPX V G -20
+KPX V A -102
+
+KPX W y -15
+KPX W u -30
+KPX W semicolon -33
+KPX W period -106
+KPX W o -46
+KPX W i -10
+KPX W hyphen -35
+KPX W e -47
+KPX W comma -106
+KPX W colon -15
+KPX W a -50
+KPX W O -20
+KPX W A -58
+
+KPX Y u -52
+KPX Y semicolon -23
+KPX Y period -145
+KPX Y o -89
+KPX Y hyphen -100
+KPX Y e -89
+KPX Y comma -145
+KPX Y colon -10
+KPX Y a -93
+KPX Y O -30
+KPX Y A -80
+
+KPX a t 5
+KPX a p 20
+KPX a b 5
+
+KPX b y -20
+KPX b v -20
+
+KPX c y -20
+KPX c l -15
+KPX c k -15
+
+KPX comma space -50
+KPX comma quoteright -70
+KPX comma quotedblright -70
+
+KPX e y -20
+KPX e x -20
+KPX e w -20
+KPX e v -20
+
+KPX f period -40
+KPX f o -20
+KPX f l -15
+KPX f i -15
+KPX f f -20
+KPX f dotlessi -15
+KPX f comma -40
+KPX f a -15
+
+KPX g i 25
+KPX g a 15
+
+KPX h y -30
+
+KPX k y -5
+KPX k o -30
+KPX k e -40
+
+KPX m y -20
+KPX m u -20
+
+KPX n y -15
+KPX n v -30
+
+KPX o y -20
+KPX o x -30
+KPX o w -20
+KPX o v -30
+
+KPX p y -20
+
+KPX period space -50
+KPX period quoteright -70
+KPX period quotedblright -70
+
+KPX quotedblleft A -50
+
+KPX quotedblright space -50
+
+KPX quoteleft quoteleft -80
+KPX quoteleft A -50
+
+KPX quoteright v -10
+KPX quoteright t 10
+KPX quoteright space -50
+KPX quoteright s -15
+KPX quoteright r -20
+KPX quoteright quoteright -80
+KPX quoteright d -50
+
+KPX r y 40
+KPX r v 40
+KPX r u 20
+KPX r t 20
+KPX r s 20
+KPX r q -8
+KPX r period -73
+KPX r p 20
+KPX r o -15
+KPX r n 21
+KPX r m 15
+KPX r l 20
+KPX r k 5
+KPX r i 20
+KPX r hyphen -60
+KPX r g 1
+KPX r e -4
+KPX r d -6
+KPX r comma -75
+KPX r c -7
+
+KPX s period 20
+KPX s comma 20
+
+KPX space quoteleft -50
+KPX space quotedblleft -50
+KPX space Y -60
+KPX space W -25
+KPX space V -80
+KPX space T -25
+KPX space A -20
+
+KPX v period -90
+KPX v o -20
+KPX v e -20
+KPX v comma -90
+KPX v a -30
+
+KPX w period -90
+KPX w o -30
+KPX w e -20
+KPX w comma -90
+KPX w a -30
+
+KPX x e -20
+
+KPX y period -100
+KPX y o -30
+KPX y e -20
+KPX y comma -100
+KPX y c -35
+KPX y a -30
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 192 170 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 132 170 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 152 170 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 192 170 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 215 135 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 162 170 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 82 170 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 22 170 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 42 170 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 82 170 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -13 170 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -98 170 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -78 170 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -63 170 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 162 170 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 242 170 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 182 170 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 202 170 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 242 170 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 212 170 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 22 170 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 177 170 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 82 170 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 102 170 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 107 170 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 167 170 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 92 170 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 37 170 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 120 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 60 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 80 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 120 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 150 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 90 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 110 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 50 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 70 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 110 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -65 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -150 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -130 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -115 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 60 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 110 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 50 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 70 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 110 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 80 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron -50 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 125 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 30 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 50 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 55 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 115 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 40 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron -15 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Bookman-Demi.afm b/tlt3.0/library/afm/Bookman-Demi.afm
new file mode 100644
index 0000000..51cb737
--- /dev/null
+++ b/tlt3.0/library/afm/Bookman-Demi.afm
@@ -0,0 +1,416 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Jan 21 16:13:29 1992
+Comment UniqueID 37831
+Comment VMusage 31983 38875
+FontName Bookman-Demi
+FullName ITC Bookman Demi
+FamilyName ITC Bookman
+Weight Demi
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -194 -250 1346 934
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.ITC Bookman is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 502
+Ascender 725
+Descender -212
+StartCharMetrics 228
+C 32 ; WX 340 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 360 ; N exclam ; B 82 -8 282 698 ;
+C 34 ; WX 420 ; N quotedbl ; B 11 379 369 698 ;
+C 35 ; WX 660 ; N numbersign ; B 84 0 576 681 ;
+C 36 ; WX 660 ; N dollar ; B 48 -119 620 805 ;
+C 37 ; WX 940 ; N percent ; B 12 -8 924 698 ;
+C 38 ; WX 800 ; N ampersand ; B 21 -17 772 698 ;
+C 39 ; WX 320 ; N quoteright ; B 82 440 242 698 ;
+C 40 ; WX 320 ; N parenleft ; B 48 -150 289 749 ;
+C 41 ; WX 320 ; N parenright ; B 20 -150 262 749 ;
+C 42 ; WX 460 ; N asterisk ; B 62 317 405 697 ;
+C 43 ; WX 600 ; N plus ; B 51 9 555 514 ;
+C 44 ; WX 340 ; N comma ; B 78 -124 257 162 ;
+C 45 ; WX 360 ; N hyphen ; B 20 210 340 318 ;
+C 46 ; WX 340 ; N period ; B 76 -8 258 172 ;
+C 47 ; WX 600 ; N slash ; B 50 -149 555 725 ;
+C 48 ; WX 660 ; N zero ; B 30 -17 639 698 ;
+C 49 ; WX 660 ; N one ; B 137 0 568 681 ;
+C 50 ; WX 660 ; N two ; B 41 0 628 698 ;
+C 51 ; WX 660 ; N three ; B 37 -17 631 698 ;
+C 52 ; WX 660 ; N four ; B 19 0 649 681 ;
+C 53 ; WX 660 ; N five ; B 44 -17 623 723 ;
+C 54 ; WX 660 ; N six ; B 34 -17 634 698 ;
+C 55 ; WX 660 ; N seven ; B 36 0 632 681 ;
+C 56 ; WX 660 ; N eight ; B 36 -17 633 698 ;
+C 57 ; WX 660 ; N nine ; B 33 -17 636 698 ;
+C 58 ; WX 340 ; N colon ; B 76 -8 258 515 ;
+C 59 ; WX 340 ; N semicolon ; B 75 -124 259 515 ;
+C 60 ; WX 600 ; N less ; B 49 -9 558 542 ;
+C 61 ; WX 600 ; N equal ; B 51 109 555 421 ;
+C 62 ; WX 600 ; N greater ; B 48 -9 557 542 ;
+C 63 ; WX 660 ; N question ; B 61 -8 608 698 ;
+C 64 ; WX 820 ; N at ; B 60 -17 758 698 ;
+C 65 ; WX 720 ; N A ; B -34 0 763 681 ;
+C 66 ; WX 720 ; N B ; B 20 0 693 681 ;
+C 67 ; WX 740 ; N C ; B 35 -17 724 698 ;
+C 68 ; WX 780 ; N D ; B 20 0 748 681 ;
+C 69 ; WX 720 ; N E ; B 20 0 724 681 ;
+C 70 ; WX 680 ; N F ; B 20 0 686 681 ;
+C 71 ; WX 780 ; N G ; B 35 -17 773 698 ;
+C 72 ; WX 820 ; N H ; B 20 0 800 681 ;
+C 73 ; WX 400 ; N I ; B 20 0 379 681 ;
+C 74 ; WX 640 ; N J ; B -12 -17 622 681 ;
+C 75 ; WX 800 ; N K ; B 20 0 796 681 ;
+C 76 ; WX 640 ; N L ; B 20 0 668 681 ;
+C 77 ; WX 940 ; N M ; B 20 0 924 681 ;
+C 78 ; WX 740 ; N N ; B 20 0 724 681 ;
+C 79 ; WX 800 ; N O ; B 35 -17 769 698 ;
+C 80 ; WX 660 ; N P ; B 20 0 658 681 ;
+C 81 ; WX 800 ; N Q ; B 35 -226 775 698 ;
+C 82 ; WX 780 ; N R ; B 20 0 783 681 ;
+C 83 ; WX 660 ; N S ; B 21 -17 639 698 ;
+C 84 ; WX 700 ; N T ; B -4 0 703 681 ;
+C 85 ; WX 740 ; N U ; B 15 -17 724 681 ;
+C 86 ; WX 720 ; N V ; B -20 0 730 681 ;
+C 87 ; WX 940 ; N W ; B -20 0 963 681 ;
+C 88 ; WX 780 ; N X ; B 1 0 770 681 ;
+C 89 ; WX 700 ; N Y ; B -20 0 718 681 ;
+C 90 ; WX 640 ; N Z ; B 6 0 635 681 ;
+C 91 ; WX 300 ; N bracketleft ; B 75 -138 285 725 ;
+C 92 ; WX 600 ; N backslash ; B 50 0 555 725 ;
+C 93 ; WX 300 ; N bracketright ; B 21 -138 231 725 ;
+C 94 ; WX 600 ; N asciicircum ; B 52 281 554 681 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 320 ; N quoteleft ; B 82 440 242 698 ;
+C 97 ; WX 580 ; N a ; B 28 -8 588 515 ;
+C 98 ; WX 600 ; N b ; B -20 -8 568 725 ;
+C 99 ; WX 580 ; N c ; B 31 -8 550 515 ;
+C 100 ; WX 640 ; N d ; B 31 -8 622 725 ;
+C 101 ; WX 580 ; N e ; B 31 -8 548 515 ;
+C 102 ; WX 380 ; N f ; B 22 0 461 741 ; L i fi ; L l fl ;
+C 103 ; WX 580 ; N g ; B 9 -243 583 595 ;
+C 104 ; WX 680 ; N h ; B 22 0 654 725 ;
+C 105 ; WX 360 ; N i ; B 22 0 335 729 ;
+C 106 ; WX 340 ; N j ; B -94 -221 278 729 ;
+C 107 ; WX 660 ; N k ; B 22 0 643 725 ;
+C 108 ; WX 340 ; N l ; B 9 0 322 725 ;
+C 109 ; WX 1000 ; N m ; B 22 0 980 515 ;
+C 110 ; WX 680 ; N n ; B 22 0 652 515 ;
+C 111 ; WX 620 ; N o ; B 31 -8 585 515 ;
+C 112 ; WX 640 ; N p ; B 22 -212 611 515 ;
+C 113 ; WX 620 ; N q ; B 31 -212 633 515 ;
+C 114 ; WX 460 ; N r ; B 22 0 462 502 ;
+C 115 ; WX 520 ; N s ; B 22 -8 492 515 ;
+C 116 ; WX 460 ; N t ; B 22 -8 445 660 ;
+C 117 ; WX 660 ; N u ; B 22 -8 653 502 ;
+C 118 ; WX 600 ; N v ; B -6 0 593 502 ;
+C 119 ; WX 800 ; N w ; B -6 0 810 502 ;
+C 120 ; WX 600 ; N x ; B 8 0 591 502 ;
+C 121 ; WX 620 ; N y ; B 6 -221 613 502 ;
+C 122 ; WX 560 ; N z ; B 22 0 547 502 ;
+C 123 ; WX 320 ; N braceleft ; B 14 -139 301 726 ;
+C 124 ; WX 600 ; N bar ; B 243 -250 362 750 ;
+C 125 ; WX 320 ; N braceright ; B 15 -140 302 725 ;
+C 126 ; WX 600 ; N asciitilde ; B 51 162 555 368 ;
+C 161 ; WX 360 ; N exclamdown ; B 84 -191 284 515 ;
+C 162 ; WX 660 ; N cent ; B 133 17 535 674 ;
+C 163 ; WX 660 ; N sterling ; B 10 -17 659 698 ;
+C 164 ; WX 120 ; N fraction ; B -194 0 312 681 ;
+C 165 ; WX 660 ; N yen ; B -28 0 696 681 ;
+C 166 ; WX 660 ; N florin ; B -46 -209 674 749 ;
+C 167 ; WX 600 ; N section ; B 36 -153 560 698 ;
+C 168 ; WX 660 ; N currency ; B 77 88 584 593 ;
+C 169 ; WX 240 ; N quotesingle ; B 42 379 178 698 ;
+C 170 ; WX 540 ; N quotedblleft ; B 82 439 449 698 ;
+C 171 ; WX 400 ; N guillemotleft ; B 34 101 360 457 ;
+C 172 ; WX 220 ; N guilsinglleft ; B 34 101 188 457 ;
+C 173 ; WX 220 ; N guilsinglright ; B 34 101 188 457 ;
+C 174 ; WX 740 ; N fi ; B 22 0 710 741 ;
+C 175 ; WX 740 ; N fl ; B 22 0 710 741 ;
+C 177 ; WX 500 ; N endash ; B -25 212 525 318 ;
+C 178 ; WX 440 ; N dagger ; B 33 -156 398 698 ;
+C 179 ; WX 380 ; N daggerdbl ; B 8 -156 380 698 ;
+C 180 ; WX 340 ; N periodcentered ; B 76 175 258 355 ;
+C 182 ; WX 800 ; N paragraph ; B 51 0 698 681 ;
+C 183 ; WX 460 ; N bullet ; B 60 170 404 511 ;
+C 184 ; WX 320 ; N quotesinglbase ; B 82 -114 242 144 ;
+C 185 ; WX 540 ; N quotedblbase ; B 82 -114 450 144 ;
+C 186 ; WX 540 ; N quotedblright ; B 82 440 449 698 ;
+C 187 ; WX 400 ; N guillemotright ; B 34 101 360 457 ;
+C 188 ; WX 1000 ; N ellipsis ; B 76 -8 924 172 ;
+C 189 ; WX 1360 ; N perthousand ; B 12 -8 1346 698 ;
+C 191 ; WX 660 ; N questiondown ; B 62 -191 609 515 ;
+C 193 ; WX 400 ; N grave ; B 68 547 327 730 ;
+C 194 ; WX 400 ; N acute ; B 68 547 327 731 ;
+C 195 ; WX 500 ; N circumflex ; B 68 555 430 731 ;
+C 196 ; WX 480 ; N tilde ; B 69 556 421 691 ;
+C 197 ; WX 460 ; N macron ; B 68 577 383 663 ;
+C 198 ; WX 500 ; N breve ; B 68 553 429 722 ;
+C 199 ; WX 320 ; N dotaccent ; B 68 536 259 730 ;
+C 200 ; WX 500 ; N dieresis ; B 68 560 441 698 ;
+C 202 ; WX 340 ; N ring ; B 68 552 275 755 ;
+C 203 ; WX 360 ; N cedilla ; B 68 -213 284 0 ;
+C 205 ; WX 440 ; N hungarumlaut ; B 68 554 365 741 ;
+C 206 ; WX 320 ; N ogonek ; B 68 -163 246 0 ;
+C 207 ; WX 500 ; N caron ; B 68 541 430 717 ;
+C 208 ; WX 1000 ; N emdash ; B -25 212 1025 318 ;
+C 225 ; WX 1140 ; N AE ; B -34 0 1149 681 ;
+C 227 ; WX 400 ; N ordfeminine ; B 27 383 396 698 ;
+C 232 ; WX 640 ; N Lslash ; B 20 0 668 681 ;
+C 233 ; WX 800 ; N Oslash ; B 35 -110 771 781 ;
+C 234 ; WX 1220 ; N OE ; B 35 -17 1219 698 ;
+C 235 ; WX 400 ; N ordmasculine ; B 17 383 383 698 ;
+C 241 ; WX 880 ; N ae ; B 28 -8 852 515 ;
+C 245 ; WX 360 ; N dotlessi ; B 22 0 335 502 ;
+C 248 ; WX 340 ; N lslash ; B 9 0 322 725 ;
+C 249 ; WX 620 ; N oslash ; B 31 -40 586 551 ;
+C 250 ; WX 940 ; N oe ; B 31 -8 908 515 ;
+C 251 ; WX 660 ; N germandbls ; B -61 -91 644 699 ;
+C -1 ; WX 580 ; N ecircumflex ; B 31 -8 548 731 ;
+C -1 ; WX 580 ; N edieresis ; B 31 -8 548 698 ;
+C -1 ; WX 580 ; N aacute ; B 28 -8 588 731 ;
+C -1 ; WX 740 ; N registered ; B 23 -17 723 698 ;
+C -1 ; WX 360 ; N icircumflex ; B -2 0 360 731 ;
+C -1 ; WX 660 ; N udieresis ; B 22 -8 653 698 ;
+C -1 ; WX 620 ; N ograve ; B 31 -8 585 730 ;
+C -1 ; WX 660 ; N uacute ; B 22 -8 653 731 ;
+C -1 ; WX 660 ; N ucircumflex ; B 22 -8 653 731 ;
+C -1 ; WX 720 ; N Aacute ; B -34 0 763 910 ;
+C -1 ; WX 360 ; N igrave ; B 22 0 335 730 ;
+C -1 ; WX 400 ; N Icircumflex ; B 18 0 380 910 ;
+C -1 ; WX 580 ; N ccedilla ; B 31 -213 550 515 ;
+C -1 ; WX 580 ; N adieresis ; B 28 -8 588 698 ;
+C -1 ; WX 720 ; N Ecircumflex ; B 20 0 724 910 ;
+C -1 ; WX 520 ; N scaron ; B 22 -8 492 717 ;
+C -1 ; WX 640 ; N thorn ; B 22 -212 611 725 ;
+C -1 ; WX 980 ; N trademark ; B 42 277 982 681 ;
+C -1 ; WX 580 ; N egrave ; B 31 -8 548 730 ;
+C -1 ; WX 396 ; N threesuperior ; B 5 269 391 698 ;
+C -1 ; WX 560 ; N zcaron ; B 22 0 547 717 ;
+C -1 ; WX 580 ; N atilde ; B 28 -8 588 691 ;
+C -1 ; WX 580 ; N aring ; B 28 -8 588 755 ;
+C -1 ; WX 620 ; N ocircumflex ; B 31 -8 585 731 ;
+C -1 ; WX 720 ; N Edieresis ; B 20 0 724 877 ;
+C -1 ; WX 990 ; N threequarters ; B 15 0 967 692 ;
+C -1 ; WX 620 ; N ydieresis ; B 6 -221 613 698 ;
+C -1 ; WX 620 ; N yacute ; B 6 -221 613 731 ;
+C -1 ; WX 360 ; N iacute ; B 22 0 335 731 ;
+C -1 ; WX 720 ; N Acircumflex ; B -34 0 763 910 ;
+C -1 ; WX 740 ; N Uacute ; B 15 -17 724 910 ;
+C -1 ; WX 580 ; N eacute ; B 31 -8 548 731 ;
+C -1 ; WX 800 ; N Ograve ; B 35 -17 769 909 ;
+C -1 ; WX 580 ; N agrave ; B 28 -8 588 730 ;
+C -1 ; WX 740 ; N Udieresis ; B 15 -17 724 877 ;
+C -1 ; WX 580 ; N acircumflex ; B 28 -8 588 731 ;
+C -1 ; WX 400 ; N Igrave ; B 20 0 379 909 ;
+C -1 ; WX 396 ; N twosuperior ; B 14 279 396 698 ;
+C -1 ; WX 740 ; N Ugrave ; B 15 -17 724 909 ;
+C -1 ; WX 990 ; N onequarter ; B 65 0 967 681 ;
+C -1 ; WX 740 ; N Ucircumflex ; B 15 -17 724 910 ;
+C -1 ; WX 660 ; N Scaron ; B 21 -17 639 896 ;
+C -1 ; WX 400 ; N Idieresis ; B 18 0 391 877 ;
+C -1 ; WX 360 ; N idieresis ; B -2 0 371 698 ;
+C -1 ; WX 720 ; N Egrave ; B 20 0 724 909 ;
+C -1 ; WX 800 ; N Oacute ; B 35 -17 769 910 ;
+C -1 ; WX 600 ; N divide ; B 51 9 555 521 ;
+C -1 ; WX 720 ; N Atilde ; B -34 0 763 870 ;
+C -1 ; WX 720 ; N Aring ; B -34 0 763 934 ;
+C -1 ; WX 800 ; N Odieresis ; B 35 -17 769 877 ;
+C -1 ; WX 720 ; N Adieresis ; B -34 0 763 877 ;
+C -1 ; WX 740 ; N Ntilde ; B 20 0 724 870 ;
+C -1 ; WX 640 ; N Zcaron ; B 6 0 635 896 ;
+C -1 ; WX 660 ; N Thorn ; B 20 0 658 681 ;
+C -1 ; WX 400 ; N Iacute ; B 20 0 379 910 ;
+C -1 ; WX 600 ; N plusminus ; B 51 0 555 514 ;
+C -1 ; WX 600 ; N multiply ; B 48 10 552 514 ;
+C -1 ; WX 720 ; N Eacute ; B 20 0 724 910 ;
+C -1 ; WX 700 ; N Ydieresis ; B -20 0 718 877 ;
+C -1 ; WX 396 ; N onesuperior ; B 65 279 345 687 ;
+C -1 ; WX 660 ; N ugrave ; B 22 -8 653 730 ;
+C -1 ; WX 600 ; N logicalnot ; B 51 129 555 421 ;
+C -1 ; WX 680 ; N ntilde ; B 22 0 652 691 ;
+C -1 ; WX 800 ; N Otilde ; B 35 -17 769 870 ;
+C -1 ; WX 620 ; N otilde ; B 31 -8 585 691 ;
+C -1 ; WX 740 ; N Ccedilla ; B 35 -213 724 698 ;
+C -1 ; WX 720 ; N Agrave ; B -34 0 763 909 ;
+C -1 ; WX 990 ; N onehalf ; B 65 0 980 681 ;
+C -1 ; WX 780 ; N Eth ; B 20 0 748 681 ;
+C -1 ; WX 400 ; N degree ; B 50 398 350 698 ;
+C -1 ; WX 700 ; N Yacute ; B -20 0 718 910 ;
+C -1 ; WX 800 ; N Ocircumflex ; B 35 -17 769 910 ;
+C -1 ; WX 620 ; N oacute ; B 31 -8 585 731 ;
+C -1 ; WX 660 ; N mu ; B 22 -221 653 502 ;
+C -1 ; WX 600 ; N minus ; B 51 207 555 323 ;
+C -1 ; WX 620 ; N eth ; B 31 -8 585 741 ;
+C -1 ; WX 620 ; N odieresis ; B 31 -8 585 698 ;
+C -1 ; WX 740 ; N copyright ; B 23 -17 723 698 ;
+C -1 ; WX 600 ; N brokenbar ; B 243 -175 362 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 90
+
+KPX A y -1
+KPX A w -9
+KPX A v -8
+KPX A Y -52
+KPX A W -20
+KPX A V -68
+KPX A T -40
+
+KPX F period -132
+KPX F comma -130
+KPX F A -59
+
+KPX L y 19
+KPX L Y -35
+KPX L W -41
+KPX L V -50
+KPX L T -4
+
+KPX P period -128
+KPX P comma -129
+KPX P A -46
+
+KPX R y -8
+KPX R Y -20
+KPX R W -24
+KPX R V -29
+KPX R T -4
+
+KPX T semicolon 5
+KPX T s -10
+KPX T r 27
+KPX T period -122
+KPX T o -28
+KPX T i 27
+KPX T hyphen -10
+KPX T e -29
+KPX T comma -122
+KPX T colon 7
+KPX T c -29
+KPX T a -24
+KPX T A -42
+
+KPX V y 12
+KPX V u -11
+KPX V semicolon -38
+KPX V r -15
+KPX V period -105
+KPX V o -79
+KPX V i 15
+KPX V hyphen -10
+KPX V e -80
+KPX V comma -103
+KPX V colon -37
+KPX V a -74
+KPX V A -88
+
+KPX W y 12
+KPX W u -11
+KPX W semicolon -38
+KPX W r -15
+KPX W period -105
+KPX W o -78
+KPX W i 15
+KPX W hyphen -10
+KPX W e -79
+KPX W comma -103
+KPX W colon -37
+KPX W a -73
+KPX W A -60
+
+KPX Y v 24
+KPX Y u -13
+KPX Y semicolon -34
+KPX Y q -66
+KPX Y period -105
+KPX Y p -23
+KPX Y o -66
+KPX Y i 2
+KPX Y hyphen -10
+KPX Y e -67
+KPX Y comma -103
+KPX Y colon -32
+KPX Y a -60
+KPX Y A -56
+
+KPX f f 21
+
+KPX r q -9
+KPX r period -102
+KPX r o -9
+KPX r n 20
+KPX r m 20
+KPX r hyphen -10
+KPX r h -23
+KPX r g -9
+KPX r f 20
+KPX r e -10
+KPX r d -10
+KPX r comma -101
+KPX r c -9
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 179 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 110 179 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 110 179 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 160 179 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 190 179 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 120 179 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 160 179 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 110 179 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 110 179 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 160 179 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 179 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -50 179 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -50 179 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 179 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 130 179 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 200 179 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 150 179 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 150 179 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 200 179 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 160 179 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 80 179 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 170 179 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 120 179 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 120 179 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 170 179 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 150 179 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 100 179 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 70 179 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 90 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 40 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 40 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 90 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 100 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 30 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 90 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 40 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 40 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 90 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -20 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -70 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -70 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -20 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 80 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 110 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 60 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 60 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 110 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 50 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 10 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 130 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 80 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 80 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 130 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 110 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 60 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 30 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Bookman-DemiItalic.afm b/tlt3.0/library/afm/Bookman-DemiItalic.afm
new file mode 100644
index 0000000..4b05c18
--- /dev/null
+++ b/tlt3.0/library/afm/Bookman-DemiItalic.afm
@@ -0,0 +1,418 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Jan 21 16:12:43 1992
+Comment UniqueID 37832
+Comment VMusage 32139 39031
+FontName Bookman-DemiItalic
+FullName ITC Bookman Demi Italic
+FamilyName ITC Bookman
+Weight Demi
+ItalicAngle -10
+IsFixedPitch false
+FontBBox -231 -250 1333 941
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.ITC Bookman is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 515
+Ascender 732
+Descender -213
+StartCharMetrics 228
+C 32 ; WX 340 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 320 ; N exclam ; B 86 -8 366 698 ;
+C 34 ; WX 380 ; N quotedbl ; B 140 371 507 697 ;
+C 35 ; WX 680 ; N numbersign ; B 157 0 649 681 ;
+C 36 ; WX 680 ; N dollar ; B 45 -164 697 790 ;
+C 37 ; WX 880 ; N percent ; B 106 -17 899 698 ;
+C 38 ; WX 980 ; N ampersand ; B 48 -17 1016 698 ;
+C 39 ; WX 320 ; N quoteright ; B 171 420 349 698 ;
+C 40 ; WX 260 ; N parenleft ; B 31 -134 388 741 ;
+C 41 ; WX 260 ; N parenright ; B -35 -134 322 741 ;
+C 42 ; WX 460 ; N asterisk ; B 126 346 508 698 ;
+C 43 ; WX 600 ; N plus ; B 91 9 595 514 ;
+C 44 ; WX 340 ; N comma ; B 100 -124 298 185 ;
+C 45 ; WX 280 ; N hyphen ; B 59 218 319 313 ;
+C 46 ; WX 340 ; N period ; B 106 -8 296 177 ;
+C 47 ; WX 360 ; N slash ; B 9 -106 502 742 ;
+C 48 ; WX 680 ; N zero ; B 87 -17 703 698 ;
+C 49 ; WX 680 ; N one ; B 123 0 565 681 ;
+C 50 ; WX 680 ; N two ; B 67 0 674 698 ;
+C 51 ; WX 680 ; N three ; B 72 -17 683 698 ;
+C 52 ; WX 680 ; N four ; B 63 0 708 681 ;
+C 53 ; WX 680 ; N five ; B 78 -17 669 681 ;
+C 54 ; WX 680 ; N six ; B 88 -17 704 698 ;
+C 55 ; WX 680 ; N seven ; B 123 0 739 681 ;
+C 56 ; WX 680 ; N eight ; B 68 -17 686 698 ;
+C 57 ; WX 680 ; N nine ; B 71 -17 712 698 ;
+C 58 ; WX 340 ; N colon ; B 106 -8 356 515 ;
+C 59 ; WX 340 ; N semicolon ; B 100 -124 352 515 ;
+C 60 ; WX 620 ; N less ; B 79 -9 588 540 ;
+C 61 ; WX 600 ; N equal ; B 91 109 595 421 ;
+C 62 ; WX 620 ; N greater ; B 89 -9 598 540 ;
+C 63 ; WX 620 ; N question ; B 145 -8 668 698 ;
+C 64 ; WX 780 ; N at ; B 80 -17 790 698 ;
+C 65 ; WX 720 ; N A ; B -27 0 769 681 ;
+C 66 ; WX 720 ; N B ; B 14 0 762 681 ;
+C 67 ; WX 700 ; N C ; B 78 -17 754 698 ;
+C 68 ; WX 760 ; N D ; B 14 0 805 681 ;
+C 69 ; WX 720 ; N E ; B 14 0 777 681 ;
+C 70 ; WX 660 ; N F ; B 14 0 763 681 ;
+C 71 ; WX 760 ; N G ; B 77 -17 828 698 ;
+C 72 ; WX 800 ; N H ; B 14 0 910 681 ;
+C 73 ; WX 380 ; N I ; B 14 0 485 681 ;
+C 74 ; WX 620 ; N J ; B 8 -17 721 681 ;
+C 75 ; WX 780 ; N K ; B 14 0 879 681 ;
+C 76 ; WX 640 ; N L ; B 14 0 725 681 ;
+C 77 ; WX 860 ; N M ; B 14 0 970 681 ;
+C 78 ; WX 740 ; N N ; B 14 0 845 681 ;
+C 79 ; WX 760 ; N O ; B 78 -17 806 698 ;
+C 80 ; WX 640 ; N P ; B -6 0 724 681 ;
+C 81 ; WX 760 ; N Q ; B 37 -213 805 698 ;
+C 82 ; WX 740 ; N R ; B 14 0 765 681 ;
+C 83 ; WX 700 ; N S ; B 59 -17 731 698 ;
+C 84 ; WX 700 ; N T ; B 70 0 802 681 ;
+C 85 ; WX 740 ; N U ; B 112 -17 855 681 ;
+C 86 ; WX 660 ; N V ; B 72 0 819 681 ;
+C 87 ; WX 1000 ; N W ; B 72 0 1090 681 ;
+C 88 ; WX 740 ; N X ; B -7 0 835 681 ;
+C 89 ; WX 660 ; N Y ; B 72 0 817 681 ;
+C 90 ; WX 680 ; N Z ; B 23 0 740 681 ;
+C 91 ; WX 260 ; N bracketleft ; B 9 -118 374 741 ;
+C 92 ; WX 580 ; N backslash ; B 73 0 575 741 ;
+C 93 ; WX 260 ; N bracketright ; B -18 -118 347 741 ;
+C 94 ; WX 620 ; N asciicircum ; B 92 281 594 681 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 320 ; N quoteleft ; B 155 420 333 698 ;
+C 97 ; WX 680 ; N a ; B 84 -8 735 515 ;
+C 98 ; WX 600 ; N b ; B 57 -8 633 732 ;
+C 99 ; WX 560 ; N c ; B 58 -8 597 515 ;
+C 100 ; WX 680 ; N d ; B 60 -8 714 732 ;
+C 101 ; WX 560 ; N e ; B 59 -8 596 515 ;
+C 102 ; WX 420 ; N f ; B -192 -213 641 741 ; L i fi ; L l fl ;
+C 103 ; WX 620 ; N g ; B 21 -213 669 515 ;
+C 104 ; WX 700 ; N h ; B 93 -8 736 732 ;
+C 105 ; WX 380 ; N i ; B 83 -8 420 755 ;
+C 106 ; WX 320 ; N j ; B -160 -213 392 755 ;
+C 107 ; WX 700 ; N k ; B 97 -8 732 732 ;
+C 108 ; WX 380 ; N l ; B 109 -8 410 732 ;
+C 109 ; WX 960 ; N m ; B 83 -8 996 515 ;
+C 110 ; WX 680 ; N n ; B 83 -8 715 515 ;
+C 111 ; WX 600 ; N o ; B 59 -8 627 515 ;
+C 112 ; WX 660 ; N p ; B -24 -213 682 515 ;
+C 113 ; WX 620 ; N q ; B 60 -213 640 515 ;
+C 114 ; WX 500 ; N r ; B 84 0 582 515 ;
+C 115 ; WX 540 ; N s ; B 32 -8 573 515 ;
+C 116 ; WX 440 ; N t ; B 106 -8 488 658 ;
+C 117 ; WX 680 ; N u ; B 83 -8 720 507 ;
+C 118 ; WX 540 ; N v ; B 56 -8 572 515 ;
+C 119 ; WX 860 ; N w ; B 56 -8 891 515 ;
+C 120 ; WX 620 ; N x ; B 10 -8 654 515 ;
+C 121 ; WX 600 ; N y ; B 25 -213 642 507 ;
+C 122 ; WX 560 ; N z ; B 36 -8 586 515 ;
+C 123 ; WX 300 ; N braceleft ; B 49 -123 413 742 ;
+C 124 ; WX 620 ; N bar ; B 303 -250 422 750 ;
+C 125 ; WX 300 ; N braceright ; B -8 -114 356 751 ;
+C 126 ; WX 620 ; N asciitilde ; B 101 162 605 368 ;
+C 161 ; WX 320 ; N exclamdown ; B 64 -191 344 515 ;
+C 162 ; WX 680 ; N cent ; B 161 25 616 718 ;
+C 163 ; WX 680 ; N sterling ; B 0 -17 787 698 ;
+C 164 ; WX 120 ; N fraction ; B -144 0 382 681 ;
+C 165 ; WX 680 ; N yen ; B 92 0 782 681 ;
+C 166 ; WX 680 ; N florin ; B -28 -199 743 741 ;
+C 167 ; WX 620 ; N section ; B 46 -137 638 698 ;
+C 168 ; WX 680 ; N currency ; B 148 85 637 571 ;
+C 169 ; WX 180 ; N quotesingle ; B 126 370 295 696 ;
+C 170 ; WX 520 ; N quotedblleft ; B 156 420 545 698 ;
+C 171 ; WX 380 ; N guillemotleft ; B 62 84 406 503 ;
+C 172 ; WX 220 ; N guilsinglleft ; B 62 84 249 503 ;
+C 173 ; WX 220 ; N guilsinglright ; B 62 84 249 503 ;
+C 174 ; WX 820 ; N fi ; B -191 -213 850 741 ;
+C 175 ; WX 820 ; N fl ; B -191 -213 850 741 ;
+C 177 ; WX 500 ; N endash ; B 40 219 573 311 ;
+C 178 ; WX 420 ; N dagger ; B 89 -137 466 698 ;
+C 179 ; WX 420 ; N daggerdbl ; B 79 -137 486 698 ;
+C 180 ; WX 340 ; N periodcentered ; B 126 173 316 358 ;
+C 182 ; WX 680 ; N paragraph ; B 137 0 715 681 ;
+C 183 ; WX 360 ; N bullet ; B 60 170 404 511 ;
+C 184 ; WX 300 ; N quotesinglbase ; B 106 -112 284 166 ;
+C 185 ; WX 520 ; N quotedblbase ; B 106 -112 495 166 ;
+C 186 ; WX 520 ; N quotedblright ; B 171 420 560 698 ;
+C 187 ; WX 380 ; N guillemotright ; B 62 84 406 503 ;
+C 188 ; WX 1000 ; N ellipsis ; B 86 -8 942 177 ;
+C 189 ; WX 1360 ; N perthousand ; B 106 -17 1333 698 ;
+C 191 ; WX 620 ; N questiondown ; B 83 -189 606 515 ;
+C 193 ; WX 380 ; N grave ; B 193 566 424 771 ;
+C 194 ; WX 340 ; N acute ; B 176 566 407 771 ;
+C 195 ; WX 480 ; N circumflex ; B 183 582 523 749 ;
+C 196 ; WX 480 ; N tilde ; B 178 587 533 709 ;
+C 197 ; WX 480 ; N macron ; B 177 603 531 691 ;
+C 198 ; WX 460 ; N breve ; B 177 577 516 707 ;
+C 199 ; WX 380 ; N dotaccent ; B 180 570 345 734 ;
+C 200 ; WX 520 ; N dieresis ; B 180 570 569 734 ;
+C 202 ; WX 360 ; N ring ; B 185 558 406 775 ;
+C 203 ; WX 360 ; N cedilla ; B 68 -220 289 -8 ;
+C 205 ; WX 560 ; N hungarumlaut ; B 181 560 616 775 ;
+C 206 ; WX 320 ; N ogonek ; B 68 -182 253 0 ;
+C 207 ; WX 480 ; N caron ; B 183 582 523 749 ;
+C 208 ; WX 1000 ; N emdash ; B 40 219 1073 311 ;
+C 225 ; WX 1140 ; N AE ; B -27 0 1207 681 ;
+C 227 ; WX 440 ; N ordfeminine ; B 118 400 495 685 ;
+C 232 ; WX 640 ; N Lslash ; B 14 0 724 681 ;
+C 233 ; WX 760 ; N Oslash ; B 21 -29 847 725 ;
+C 234 ; WX 1180 ; N OE ; B 94 -17 1245 698 ;
+C 235 ; WX 440 ; N ordmasculine ; B 127 400 455 685 ;
+C 241 ; WX 880 ; N ae ; B 39 -8 913 515 ;
+C 245 ; WX 380 ; N dotlessi ; B 83 -8 420 507 ;
+C 248 ; WX 380 ; N lslash ; B 63 -8 412 732 ;
+C 249 ; WX 600 ; N oslash ; B 17 -54 661 571 ;
+C 250 ; WX 920 ; N oe ; B 48 -8 961 515 ;
+C 251 ; WX 660 ; N germandbls ; B -231 -213 702 741 ;
+C -1 ; WX 560 ; N ecircumflex ; B 59 -8 596 749 ;
+C -1 ; WX 560 ; N edieresis ; B 59 -8 596 734 ;
+C -1 ; WX 680 ; N aacute ; B 84 -8 735 771 ;
+C -1 ; WX 780 ; N registered ; B 83 -17 783 698 ;
+C -1 ; WX 380 ; N icircumflex ; B 83 -8 433 749 ;
+C -1 ; WX 680 ; N udieresis ; B 83 -8 720 734 ;
+C -1 ; WX 600 ; N ograve ; B 59 -8 627 771 ;
+C -1 ; WX 680 ; N uacute ; B 83 -8 720 771 ;
+C -1 ; WX 680 ; N ucircumflex ; B 83 -8 720 749 ;
+C -1 ; WX 720 ; N Aacute ; B -27 0 769 937 ;
+C -1 ; WX 380 ; N igrave ; B 83 -8 424 771 ;
+C -1 ; WX 380 ; N Icircumflex ; B 14 0 493 915 ;
+C -1 ; WX 560 ; N ccedilla ; B 58 -220 597 515 ;
+C -1 ; WX 680 ; N adieresis ; B 84 -8 735 734 ;
+C -1 ; WX 720 ; N Ecircumflex ; B 14 0 777 915 ;
+C -1 ; WX 540 ; N scaron ; B 32 -8 573 749 ;
+C -1 ; WX 660 ; N thorn ; B -24 -213 682 732 ;
+C -1 ; WX 940 ; N trademark ; B 42 277 982 681 ;
+C -1 ; WX 560 ; N egrave ; B 59 -8 596 771 ;
+C -1 ; WX 408 ; N threesuperior ; B 86 269 483 698 ;
+C -1 ; WX 560 ; N zcaron ; B 36 -8 586 749 ;
+C -1 ; WX 680 ; N atilde ; B 84 -8 735 709 ;
+C -1 ; WX 680 ; N aring ; B 84 -8 735 775 ;
+C -1 ; WX 600 ; N ocircumflex ; B 59 -8 627 749 ;
+C -1 ; WX 720 ; N Edieresis ; B 14 0 777 900 ;
+C -1 ; WX 1020 ; N threequarters ; B 86 0 1054 691 ;
+C -1 ; WX 600 ; N ydieresis ; B 25 -213 642 734 ;
+C -1 ; WX 600 ; N yacute ; B 25 -213 642 771 ;
+C -1 ; WX 380 ; N iacute ; B 83 -8 420 771 ;
+C -1 ; WX 720 ; N Acircumflex ; B -27 0 769 915 ;
+C -1 ; WX 740 ; N Uacute ; B 112 -17 855 937 ;
+C -1 ; WX 560 ; N eacute ; B 59 -8 596 771 ;
+C -1 ; WX 760 ; N Ograve ; B 78 -17 806 937 ;
+C -1 ; WX 680 ; N agrave ; B 84 -8 735 771 ;
+C -1 ; WX 740 ; N Udieresis ; B 112 -17 855 900 ;
+C -1 ; WX 680 ; N acircumflex ; B 84 -8 735 749 ;
+C -1 ; WX 380 ; N Igrave ; B 14 0 485 937 ;
+C -1 ; WX 408 ; N twosuperior ; B 91 279 485 698 ;
+C -1 ; WX 740 ; N Ugrave ; B 112 -17 855 937 ;
+C -1 ; WX 1020 ; N onequarter ; B 118 0 1054 681 ;
+C -1 ; WX 740 ; N Ucircumflex ; B 112 -17 855 915 ;
+C -1 ; WX 700 ; N Scaron ; B 59 -17 731 915 ;
+C -1 ; WX 380 ; N Idieresis ; B 14 0 499 900 ;
+C -1 ; WX 380 ; N idieresis ; B 83 -8 479 734 ;
+C -1 ; WX 720 ; N Egrave ; B 14 0 777 937 ;
+C -1 ; WX 760 ; N Oacute ; B 78 -17 806 937 ;
+C -1 ; WX 600 ; N divide ; B 91 9 595 521 ;
+C -1 ; WX 720 ; N Atilde ; B -27 0 769 875 ;
+C -1 ; WX 720 ; N Aring ; B -27 0 769 941 ;
+C -1 ; WX 760 ; N Odieresis ; B 78 -17 806 900 ;
+C -1 ; WX 720 ; N Adieresis ; B -27 0 769 900 ;
+C -1 ; WX 740 ; N Ntilde ; B 14 0 845 875 ;
+C -1 ; WX 680 ; N Zcaron ; B 23 0 740 915 ;
+C -1 ; WX 640 ; N Thorn ; B -6 0 701 681 ;
+C -1 ; WX 380 ; N Iacute ; B 14 0 485 937 ;
+C -1 ; WX 600 ; N plusminus ; B 91 0 595 514 ;
+C -1 ; WX 600 ; N multiply ; B 91 10 595 514 ;
+C -1 ; WX 720 ; N Eacute ; B 14 0 777 937 ;
+C -1 ; WX 660 ; N Ydieresis ; B 72 0 817 900 ;
+C -1 ; WX 408 ; N onesuperior ; B 118 279 406 688 ;
+C -1 ; WX 680 ; N ugrave ; B 83 -8 720 771 ;
+C -1 ; WX 620 ; N logicalnot ; B 81 129 585 421 ;
+C -1 ; WX 680 ; N ntilde ; B 83 -8 715 709 ;
+C -1 ; WX 760 ; N Otilde ; B 78 -17 806 875 ;
+C -1 ; WX 600 ; N otilde ; B 59 -8 627 709 ;
+C -1 ; WX 700 ; N Ccedilla ; B 78 -220 754 698 ;
+C -1 ; WX 720 ; N Agrave ; B -27 0 769 937 ;
+C -1 ; WX 1020 ; N onehalf ; B 118 0 1036 681 ;
+C -1 ; WX 760 ; N Eth ; B 14 0 805 681 ;
+C -1 ; WX 400 ; N degree ; B 130 398 430 698 ;
+C -1 ; WX 660 ; N Yacute ; B 72 0 817 937 ;
+C -1 ; WX 760 ; N Ocircumflex ; B 78 -17 806 915 ;
+C -1 ; WX 600 ; N oacute ; B 59 -8 627 771 ;
+C -1 ; WX 680 ; N mu ; B 54 -213 720 507 ;
+C -1 ; WX 600 ; N minus ; B 91 207 595 323 ;
+C -1 ; WX 600 ; N eth ; B 59 -8 662 741 ;
+C -1 ; WX 600 ; N odieresis ; B 59 -8 627 734 ;
+C -1 ; WX 780 ; N copyright ; B 83 -17 783 698 ;
+C -1 ; WX 620 ; N brokenbar ; B 303 -175 422 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 92
+
+KPX A y 20
+KPX A w 20
+KPX A v 20
+KPX A Y -25
+KPX A W -35
+KPX A V -40
+KPX A T -17
+
+KPX F period -105
+KPX F comma -98
+KPX F A -35
+
+KPX L y 62
+KPX L Y -5
+KPX L W -15
+KPX L V -19
+KPX L T -26
+
+KPX P period -105
+KPX P comma -98
+KPX P A -31
+
+KPX R y 27
+KPX R Y 4
+KPX R W -4
+KPX R V -8
+KPX R T -3
+
+KPX T y 56
+KPX T w 69
+KPX T u 42
+KPX T semicolon 31
+KPX T s -1
+KPX T r 41
+KPX T period -107
+KPX T o -5
+KPX T i 42
+KPX T hyphen -20
+KPX T e -10
+KPX T comma -100
+KPX T colon 26
+KPX T c -8
+KPX T a -8
+KPX T A -42
+
+KPX V y 17
+KPX V u -1
+KPX V semicolon -22
+KPX V r 2
+KPX V period -115
+KPX V o -50
+KPX V i 32
+KPX V hyphen -20
+KPX V e -50
+KPX V comma -137
+KPX V colon -28
+KPX V a -50
+KPX V A -50
+
+KPX W y -51
+KPX W u -69
+KPX W semicolon -81
+KPX W r -66
+KPX W period -183
+KPX W o -100
+KPX W i -36
+KPX W hyphen -22
+KPX W e -100
+KPX W comma -201
+KPX W colon -86
+KPX W a -100
+KPX W A -77
+
+KPX Y v 26
+KPX Y u -1
+KPX Y semicolon -4
+KPX Y q -43
+KPX Y period -113
+KPX Y o -41
+KPX Y i 20
+KPX Y hyphen -20
+KPX Y e -46
+KPX Y comma -106
+KPX Y colon -9
+KPX Y a -45
+KPX Y A -30
+
+KPX f f 10
+
+KPX r q -3
+KPX r period -120
+KPX r o -1
+KPX r n 39
+KPX r m 39
+KPX r hyphen -20
+KPX r h -35
+KPX r g -23
+KPX r f 42
+KPX r e -6
+KPX r d -3
+KPX r comma -113
+KPX r c -5
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 190 166 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 120 166 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 100 166 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 170 166 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 200 166 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 120 166 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 190 166 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 120 166 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 100 166 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 170 166 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 20 166 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -30 166 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -70 166 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 166 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 130 166 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 210 166 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 140 166 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 140 166 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 190 166 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 140 166 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 110 166 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 200 166 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 130 166 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 130 166 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 180 166 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 160 166 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 70 166 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 100 166 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 170 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 100 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 80 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 150 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 160 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 100 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 110 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 60 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 20 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 90 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -90 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -90 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 60 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 130 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 60 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 40 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 110 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 60 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 30 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 170 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 100 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 80 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 150 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 130 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 40 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 40 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Bookman-Light.afm b/tlt3.0/library/afm/Bookman-Light.afm
new file mode 100644
index 0000000..75e019b
--- /dev/null
+++ b/tlt3.0/library/afm/Bookman-Light.afm
@@ -0,0 +1,408 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Jan 21 16:15:53 1992
+Comment UniqueID 37833
+Comment VMusage 32321 39213
+FontName Bookman-Light
+FullName ITC Bookman Light
+FamilyName ITC Bookman
+Weight Light
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -188 -251 1266 908
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.ITC Bookman is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 484
+Ascender 717
+Descender -228
+StartCharMetrics 228
+C 32 ; WX 320 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 300 ; N exclam ; B 75 -8 219 698 ;
+C 34 ; WX 380 ; N quotedbl ; B 56 458 323 698 ;
+C 35 ; WX 620 ; N numbersign ; B 65 0 556 681 ;
+C 36 ; WX 620 ; N dollar ; B 34 -109 593 791 ;
+C 37 ; WX 900 ; N percent ; B 22 -8 873 698 ;
+C 38 ; WX 800 ; N ampersand ; B 45 -17 787 698 ;
+C 39 ; WX 220 ; N quoteright ; B 46 480 178 698 ;
+C 40 ; WX 300 ; N parenleft ; B 76 -145 278 727 ;
+C 41 ; WX 300 ; N parenright ; B 17 -146 219 727 ;
+C 42 ; WX 440 ; N asterisk ; B 54 325 391 698 ;
+C 43 ; WX 600 ; N plus ; B 51 8 555 513 ;
+C 44 ; WX 320 ; N comma ; B 90 -114 223 114 ;
+C 45 ; WX 400 ; N hyphen ; B 50 232 350 292 ;
+C 46 ; WX 320 ; N period ; B 92 -8 220 123 ;
+C 47 ; WX 600 ; N slash ; B 74 -149 532 717 ;
+C 48 ; WX 620 ; N zero ; B 40 -17 586 698 ;
+C 49 ; WX 620 ; N one ; B 160 0 501 681 ;
+C 50 ; WX 620 ; N two ; B 42 0 576 698 ;
+C 51 ; WX 620 ; N three ; B 40 -17 576 698 ;
+C 52 ; WX 620 ; N four ; B 25 0 600 681 ;
+C 53 ; WX 620 ; N five ; B 60 -17 584 717 ;
+C 54 ; WX 620 ; N six ; B 45 -17 590 698 ;
+C 55 ; WX 620 ; N seven ; B 60 0 586 681 ;
+C 56 ; WX 620 ; N eight ; B 44 -17 583 698 ;
+C 57 ; WX 620 ; N nine ; B 37 -17 576 698 ;
+C 58 ; WX 320 ; N colon ; B 92 -8 220 494 ;
+C 59 ; WX 320 ; N semicolon ; B 90 -114 223 494 ;
+C 60 ; WX 600 ; N less ; B 49 -2 558 526 ;
+C 61 ; WX 600 ; N equal ; B 51 126 555 398 ;
+C 62 ; WX 600 ; N greater ; B 48 -2 557 526 ;
+C 63 ; WX 540 ; N question ; B 27 -8 514 698 ;
+C 64 ; WX 820 ; N at ; B 55 -17 755 698 ;
+C 65 ; WX 680 ; N A ; B -37 0 714 681 ;
+C 66 ; WX 740 ; N B ; B 31 0 702 681 ;
+C 67 ; WX 740 ; N C ; B 44 -17 702 698 ;
+C 68 ; WX 800 ; N D ; B 31 0 752 681 ;
+C 69 ; WX 720 ; N E ; B 31 0 705 681 ;
+C 70 ; WX 640 ; N F ; B 31 0 654 681 ;
+C 71 ; WX 800 ; N G ; B 44 -17 778 698 ;
+C 72 ; WX 800 ; N H ; B 31 0 769 681 ;
+C 73 ; WX 340 ; N I ; B 31 0 301 681 ;
+C 74 ; WX 600 ; N J ; B -23 -17 567 681 ;
+C 75 ; WX 720 ; N K ; B 31 0 750 681 ;
+C 76 ; WX 600 ; N L ; B 31 0 629 681 ;
+C 77 ; WX 920 ; N M ; B 26 0 894 681 ;
+C 78 ; WX 740 ; N N ; B 26 0 722 681 ;
+C 79 ; WX 800 ; N O ; B 44 -17 758 698 ;
+C 80 ; WX 620 ; N P ; B 31 0 613 681 ;
+C 81 ; WX 820 ; N Q ; B 44 -189 769 698 ;
+C 82 ; WX 720 ; N R ; B 31 0 757 681 ;
+C 83 ; WX 660 ; N S ; B 28 -17 634 698 ;
+C 84 ; WX 620 ; N T ; B -37 0 656 681 ;
+C 85 ; WX 780 ; N U ; B 25 -17 754 681 ;
+C 86 ; WX 700 ; N V ; B -30 0 725 681 ;
+C 87 ; WX 960 ; N W ; B -30 0 984 681 ;
+C 88 ; WX 720 ; N X ; B -30 0 755 681 ;
+C 89 ; WX 640 ; N Y ; B -30 0 666 681 ;
+C 90 ; WX 640 ; N Z ; B 10 0 656 681 ;
+C 91 ; WX 300 ; N bracketleft ; B 92 -136 258 717 ;
+C 92 ; WX 600 ; N backslash ; B 74 0 532 717 ;
+C 93 ; WX 300 ; N bracketright ; B 41 -136 207 717 ;
+C 94 ; WX 600 ; N asciicircum ; B 52 276 554 681 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 220 ; N quoteleft ; B 46 479 178 698 ;
+C 97 ; WX 580 ; N a ; B 35 -8 587 494 ;
+C 98 ; WX 620 ; N b ; B -2 -8 582 717 ;
+C 99 ; WX 520 ; N c ; B 37 -8 498 494 ;
+C 100 ; WX 620 ; N d ; B 37 -8 591 717 ;
+C 101 ; WX 520 ; N e ; B 37 -8 491 494 ;
+C 102 ; WX 320 ; N f ; B 20 0 414 734 ; L i fi ; L l fl ;
+C 103 ; WX 540 ; N g ; B 17 -243 542 567 ;
+C 104 ; WX 660 ; N h ; B 20 0 643 717 ;
+C 105 ; WX 300 ; N i ; B 20 0 288 654 ;
+C 106 ; WX 300 ; N j ; B -109 -251 214 654 ;
+C 107 ; WX 620 ; N k ; B 20 0 628 717 ;
+C 108 ; WX 300 ; N l ; B 20 0 286 717 ;
+C 109 ; WX 940 ; N m ; B 17 0 928 494 ;
+C 110 ; WX 660 ; N n ; B 20 0 649 494 ;
+C 111 ; WX 560 ; N o ; B 37 -8 526 494 ;
+C 112 ; WX 620 ; N p ; B 20 -228 583 494 ;
+C 113 ; WX 580 ; N q ; B 37 -228 589 494 ;
+C 114 ; WX 440 ; N r ; B 20 0 447 494 ;
+C 115 ; WX 520 ; N s ; B 40 -8 487 494 ;
+C 116 ; WX 380 ; N t ; B 20 -8 388 667 ;
+C 117 ; WX 680 ; N u ; B 20 -8 653 484 ;
+C 118 ; WX 520 ; N v ; B -23 0 534 484 ;
+C 119 ; WX 780 ; N w ; B -19 0 804 484 ;
+C 120 ; WX 560 ; N x ; B -16 0 576 484 ;
+C 121 ; WX 540 ; N y ; B -23 -236 549 484 ;
+C 122 ; WX 480 ; N z ; B 7 0 476 484 ;
+C 123 ; WX 280 ; N braceleft ; B 21 -136 260 717 ;
+C 124 ; WX 600 ; N bar ; B 264 -250 342 750 ;
+C 125 ; WX 280 ; N braceright ; B 21 -136 260 717 ;
+C 126 ; WX 600 ; N asciitilde ; B 52 173 556 352 ;
+C 161 ; WX 300 ; N exclamdown ; B 75 -214 219 494 ;
+C 162 ; WX 620 ; N cent ; B 116 20 511 651 ;
+C 163 ; WX 620 ; N sterling ; B 8 -17 631 698 ;
+C 164 ; WX 140 ; N fraction ; B -188 0 335 681 ;
+C 165 ; WX 620 ; N yen ; B -22 0 647 681 ;
+C 166 ; WX 620 ; N florin ; B -29 -155 633 749 ;
+C 167 ; WX 520 ; N section ; B 33 -178 486 698 ;
+C 168 ; WX 620 ; N currency ; B 58 89 563 591 ;
+C 169 ; WX 220 ; N quotesingle ; B 67 458 153 698 ;
+C 170 ; WX 400 ; N quotedblleft ; B 46 479 348 698 ;
+C 171 ; WX 360 ; N guillemotleft ; B 51 89 312 437 ;
+C 172 ; WX 240 ; N guilsinglleft ; B 51 89 189 437 ;
+C 173 ; WX 240 ; N guilsinglright ; B 51 89 189 437 ;
+C 174 ; WX 620 ; N fi ; B 20 0 608 734 ;
+C 175 ; WX 620 ; N fl ; B 20 0 606 734 ;
+C 177 ; WX 500 ; N endash ; B -15 232 515 292 ;
+C 178 ; WX 540 ; N dagger ; B 79 -156 455 698 ;
+C 179 ; WX 540 ; N daggerdbl ; B 79 -156 455 698 ;
+C 180 ; WX 320 ; N periodcentered ; B 92 196 220 327 ;
+C 182 ; WX 600 ; N paragraph ; B 14 0 577 681 ;
+C 183 ; WX 460 ; N bullet ; B 60 170 404 511 ;
+C 184 ; WX 220 ; N quotesinglbase ; B 46 -108 178 110 ;
+C 185 ; WX 400 ; N quotedblbase ; B 46 -108 348 110 ;
+C 186 ; WX 400 ; N quotedblright ; B 46 480 348 698 ;
+C 187 ; WX 360 ; N guillemotright ; B 51 89 312 437 ;
+C 188 ; WX 1000 ; N ellipsis ; B 101 -8 898 123 ;
+C 189 ; WX 1280 ; N perthousand ; B 22 -8 1266 698 ;
+C 191 ; WX 540 ; N questiondown ; B 23 -217 510 494 ;
+C 193 ; WX 340 ; N grave ; B 68 571 274 689 ;
+C 194 ; WX 340 ; N acute ; B 68 571 274 689 ;
+C 195 ; WX 420 ; N circumflex ; B 68 567 352 685 ;
+C 196 ; WX 440 ; N tilde ; B 68 572 375 661 ;
+C 197 ; WX 440 ; N macron ; B 68 587 364 635 ;
+C 198 ; WX 460 ; N breve ; B 68 568 396 687 ;
+C 199 ; WX 260 ; N dotaccent ; B 68 552 186 672 ;
+C 200 ; WX 420 ; N dieresis ; B 68 552 349 674 ;
+C 202 ; WX 320 ; N ring ; B 68 546 252 731 ;
+C 203 ; WX 320 ; N cedilla ; B 68 -200 257 0 ;
+C 205 ; WX 380 ; N hungarumlaut ; B 68 538 311 698 ;
+C 206 ; WX 320 ; N ogonek ; B 68 -145 245 0 ;
+C 207 ; WX 420 ; N caron ; B 68 554 352 672 ;
+C 208 ; WX 1000 ; N emdash ; B -15 232 1015 292 ;
+C 225 ; WX 1260 ; N AE ; B -36 0 1250 681 ;
+C 227 ; WX 420 ; N ordfeminine ; B 49 395 393 698 ;
+C 232 ; WX 600 ; N Lslash ; B 31 0 629 681 ;
+C 233 ; WX 800 ; N Oslash ; B 44 -53 758 733 ;
+C 234 ; WX 1240 ; N OE ; B 44 -17 1214 698 ;
+C 235 ; WX 420 ; N ordmasculine ; B 56 394 361 698 ;
+C 241 ; WX 860 ; N ae ; B 35 -8 832 494 ;
+C 245 ; WX 300 ; N dotlessi ; B 20 0 288 484 ;
+C 248 ; WX 320 ; N lslash ; B 20 0 291 717 ;
+C 249 ; WX 560 ; N oslash ; B 37 -40 526 534 ;
+C 250 ; WX 900 ; N oe ; B 37 -8 876 494 ;
+C 251 ; WX 660 ; N germandbls ; B -109 -110 614 698 ;
+C -1 ; WX 520 ; N ecircumflex ; B 37 -8 491 685 ;
+C -1 ; WX 520 ; N edieresis ; B 37 -8 491 674 ;
+C -1 ; WX 580 ; N aacute ; B 35 -8 587 689 ;
+C -1 ; WX 740 ; N registered ; B 23 -17 723 698 ;
+C -1 ; WX 300 ; N icircumflex ; B 8 0 292 685 ;
+C -1 ; WX 680 ; N udieresis ; B 20 -8 653 674 ;
+C -1 ; WX 560 ; N ograve ; B 37 -8 526 689 ;
+C -1 ; WX 680 ; N uacute ; B 20 -8 653 689 ;
+C -1 ; WX 680 ; N ucircumflex ; B 20 -8 653 685 ;
+C -1 ; WX 680 ; N Aacute ; B -37 0 714 866 ;
+C -1 ; WX 300 ; N igrave ; B 20 0 288 689 ;
+C -1 ; WX 340 ; N Icircumflex ; B 28 0 312 862 ;
+C -1 ; WX 520 ; N ccedilla ; B 37 -200 498 494 ;
+C -1 ; WX 580 ; N adieresis ; B 35 -8 587 674 ;
+C -1 ; WX 720 ; N Ecircumflex ; B 31 0 705 862 ;
+C -1 ; WX 520 ; N scaron ; B 40 -8 487 672 ;
+C -1 ; WX 620 ; N thorn ; B 20 -228 583 717 ;
+C -1 ; WX 980 ; N trademark ; B 34 277 930 681 ;
+C -1 ; WX 520 ; N egrave ; B 37 -8 491 689 ;
+C -1 ; WX 372 ; N threesuperior ; B 12 269 360 698 ;
+C -1 ; WX 480 ; N zcaron ; B 7 0 476 672 ;
+C -1 ; WX 580 ; N atilde ; B 35 -8 587 661 ;
+C -1 ; WX 580 ; N aring ; B 35 -8 587 731 ;
+C -1 ; WX 560 ; N ocircumflex ; B 37 -8 526 685 ;
+C -1 ; WX 720 ; N Edieresis ; B 31 0 705 851 ;
+C -1 ; WX 930 ; N threequarters ; B 52 0 889 691 ;
+C -1 ; WX 540 ; N ydieresis ; B -23 -236 549 674 ;
+C -1 ; WX 540 ; N yacute ; B -23 -236 549 689 ;
+C -1 ; WX 300 ; N iacute ; B 20 0 288 689 ;
+C -1 ; WX 680 ; N Acircumflex ; B -37 0 714 862 ;
+C -1 ; WX 780 ; N Uacute ; B 25 -17 754 866 ;
+C -1 ; WX 520 ; N eacute ; B 37 -8 491 689 ;
+C -1 ; WX 800 ; N Ograve ; B 44 -17 758 866 ;
+C -1 ; WX 580 ; N agrave ; B 35 -8 587 689 ;
+C -1 ; WX 780 ; N Udieresis ; B 25 -17 754 851 ;
+C -1 ; WX 580 ; N acircumflex ; B 35 -8 587 685 ;
+C -1 ; WX 340 ; N Igrave ; B 31 0 301 866 ;
+C -1 ; WX 372 ; N twosuperior ; B 20 279 367 698 ;
+C -1 ; WX 780 ; N Ugrave ; B 25 -17 754 866 ;
+C -1 ; WX 930 ; N onequarter ; B 80 0 869 681 ;
+C -1 ; WX 780 ; N Ucircumflex ; B 25 -17 754 862 ;
+C -1 ; WX 660 ; N Scaron ; B 28 -17 634 849 ;
+C -1 ; WX 340 ; N Idieresis ; B 28 0 309 851 ;
+C -1 ; WX 300 ; N idieresis ; B 8 0 289 674 ;
+C -1 ; WX 720 ; N Egrave ; B 31 0 705 866 ;
+C -1 ; WX 800 ; N Oacute ; B 44 -17 758 866 ;
+C -1 ; WX 600 ; N divide ; B 51 10 555 514 ;
+C -1 ; WX 680 ; N Atilde ; B -37 0 714 838 ;
+C -1 ; WX 680 ; N Aring ; B -37 0 714 908 ;
+C -1 ; WX 800 ; N Odieresis ; B 44 -17 758 851 ;
+C -1 ; WX 680 ; N Adieresis ; B -37 0 714 851 ;
+C -1 ; WX 740 ; N Ntilde ; B 26 0 722 838 ;
+C -1 ; WX 640 ; N Zcaron ; B 10 0 656 849 ;
+C -1 ; WX 620 ; N Thorn ; B 31 0 613 681 ;
+C -1 ; WX 340 ; N Iacute ; B 31 0 301 866 ;
+C -1 ; WX 600 ; N plusminus ; B 51 0 555 513 ;
+C -1 ; WX 600 ; N multiply ; B 51 9 555 513 ;
+C -1 ; WX 720 ; N Eacute ; B 31 0 705 866 ;
+C -1 ; WX 640 ; N Ydieresis ; B -30 0 666 851 ;
+C -1 ; WX 372 ; N onesuperior ; B 80 279 302 688 ;
+C -1 ; WX 680 ; N ugrave ; B 20 -8 653 689 ;
+C -1 ; WX 600 ; N logicalnot ; B 51 128 555 398 ;
+C -1 ; WX 660 ; N ntilde ; B 20 0 649 661 ;
+C -1 ; WX 800 ; N Otilde ; B 44 -17 758 838 ;
+C -1 ; WX 560 ; N otilde ; B 37 -8 526 661 ;
+C -1 ; WX 740 ; N Ccedilla ; B 44 -200 702 698 ;
+C -1 ; WX 680 ; N Agrave ; B -37 0 714 866 ;
+C -1 ; WX 930 ; N onehalf ; B 80 0 885 681 ;
+C -1 ; WX 800 ; N Eth ; B 31 0 752 681 ;
+C -1 ; WX 400 ; N degree ; B 50 398 350 698 ;
+C -1 ; WX 640 ; N Yacute ; B -30 0 666 866 ;
+C -1 ; WX 800 ; N Ocircumflex ; B 44 -17 758 862 ;
+C -1 ; WX 560 ; N oacute ; B 37 -8 526 689 ;
+C -1 ; WX 680 ; N mu ; B 20 -251 653 484 ;
+C -1 ; WX 600 ; N minus ; B 51 224 555 300 ;
+C -1 ; WX 560 ; N eth ; B 37 -8 526 734 ;
+C -1 ; WX 560 ; N odieresis ; B 37 -8 526 674 ;
+C -1 ; WX 740 ; N copyright ; B 24 -17 724 698 ;
+C -1 ; WX 600 ; N brokenbar ; B 264 -175 342 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 82
+
+KPX A y 32
+KPX A w 4
+KPX A v 7
+KPX A Y -35
+KPX A W -40
+KPX A V -56
+KPX A T 1
+
+KPX F period -46
+KPX F comma -41
+KPX F A -21
+
+KPX L y 79
+KPX L Y 13
+KPX L W 1
+KPX L V -4
+KPX L T 28
+
+KPX P period -60
+KPX P comma -55
+KPX P A -8
+
+KPX R y 59
+KPX R Y 26
+KPX R W 13
+KPX R V 8
+KPX R T 71
+
+KPX T s 16
+KPX T r 38
+KPX T period -33
+KPX T o 15
+KPX T i 42
+KPX T hyphen 90
+KPX T e 13
+KPX T comma -28
+KPX T c 14
+KPX T a 17
+KPX T A 1
+
+KPX V y 15
+KPX V u -38
+KPX V r -41
+KPX V period -40
+KPX V o -71
+KPX V i -20
+KPX V hyphen 11
+KPX V e -72
+KPX V comma -34
+KPX V a -69
+KPX V A -66
+
+KPX W y 15
+KPX W u -38
+KPX W r -41
+KPX W period -40
+KPX W o -68
+KPX W i -20
+KPX W hyphen 11
+KPX W e -69
+KPX W comma -34
+KPX W a -66
+KPX W A -64
+
+KPX Y v 15
+KPX Y u -38
+KPX Y q -55
+KPX Y period -40
+KPX Y p -31
+KPX Y o -57
+KPX Y i -37
+KPX Y hyphen 11
+KPX Y e -58
+KPX Y comma -34
+KPX Y a -54
+KPX Y A -53
+
+KPX f f 29
+
+KPX r q 9
+KPX r period -64
+KPX r o 8
+KPX r n 31
+KPX r m 31
+KPX r hyphen 70
+KPX r h -21
+KPX r g -4
+KPX r f 33
+KPX r e 7
+KPX r d 7
+KPX r comma -58
+KPX r c 7
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 200 177 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 130 177 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 130 177 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 140 177 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 180 177 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 120 177 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 220 177 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 150 177 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 150 177 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 160 177 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 20 177 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -40 177 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -40 177 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -20 177 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 150 177 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 260 177 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 190 177 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 190 177 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 200 177 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 180 177 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 120 177 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 250 177 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 180 177 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 180 177 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 190 177 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 150 177 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 110 177 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 110 177 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 120 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 80 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 80 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 120 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 130 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 70 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 90 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 50 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 50 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 90 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -20 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -60 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -60 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -20 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 110 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 110 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 70 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 70 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 110 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 60 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 50 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 170 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 130 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 130 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 170 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 100 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 60 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 30 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Bookman-LightItalic.afm b/tlt3.0/library/afm/Bookman-LightItalic.afm
new file mode 100644
index 0000000..3e6ef4c
--- /dev/null
+++ b/tlt3.0/library/afm/Bookman-LightItalic.afm
@@ -0,0 +1,411 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Jan 21 16:12:06 1992
+Comment UniqueID 37830
+Comment VMusage 33139 40031
+FontName Bookman-LightItalic
+FullName ITC Bookman Light Italic
+FamilyName ITC Bookman
+Weight Light
+ItalicAngle -10
+IsFixedPitch false
+FontBBox -228 -250 1269 883
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1989, 1992 Adobe Systems Incorporated. All Rights Reserved.ITC Bookman is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 494
+Ascender 717
+Descender -212
+StartCharMetrics 228
+C 32 ; WX 300 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 320 ; N exclam ; B 103 -8 342 698 ;
+C 34 ; WX 360 ; N quotedbl ; B 107 468 402 698 ;
+C 35 ; WX 620 ; N numbersign ; B 107 0 598 681 ;
+C 36 ; WX 620 ; N dollar ; B 78 -85 619 762 ;
+C 37 ; WX 800 ; N percent ; B 56 -8 811 691 ;
+C 38 ; WX 820 ; N ampersand ; B 65 -18 848 698 ;
+C 39 ; WX 280 ; N quoteright ; B 148 470 288 698 ;
+C 40 ; WX 280 ; N parenleft ; B 96 -146 383 727 ;
+C 41 ; WX 280 ; N parenright ; B -8 -146 279 727 ;
+C 42 ; WX 440 ; N asterisk ; B 139 324 505 698 ;
+C 43 ; WX 600 ; N plus ; B 91 43 595 548 ;
+C 44 ; WX 300 ; N comma ; B 88 -115 227 112 ;
+C 45 ; WX 320 ; N hyphen ; B 78 269 336 325 ;
+C 46 ; WX 300 ; N period ; B 96 -8 231 127 ;
+C 47 ; WX 600 ; N slash ; B 104 -149 562 717 ;
+C 48 ; WX 620 ; N zero ; B 86 -17 646 698 ;
+C 49 ; WX 620 ; N one ; B 154 0 500 681 ;
+C 50 ; WX 620 ; N two ; B 66 0 636 698 ;
+C 51 ; WX 620 ; N three ; B 55 -17 622 698 ;
+C 52 ; WX 620 ; N four ; B 69 0 634 681 ;
+C 53 ; WX 620 ; N five ; B 70 -17 614 681 ;
+C 54 ; WX 620 ; N six ; B 89 -17 657 698 ;
+C 55 ; WX 620 ; N seven ; B 143 0 672 681 ;
+C 56 ; WX 620 ; N eight ; B 61 -17 655 698 ;
+C 57 ; WX 620 ; N nine ; B 77 -17 649 698 ;
+C 58 ; WX 300 ; N colon ; B 96 -8 292 494 ;
+C 59 ; WX 300 ; N semicolon ; B 88 -114 292 494 ;
+C 60 ; WX 600 ; N less ; B 79 33 588 561 ;
+C 61 ; WX 600 ; N equal ; B 91 161 595 433 ;
+C 62 ; WX 600 ; N greater ; B 93 33 602 561 ;
+C 63 ; WX 540 ; N question ; B 114 -8 604 698 ;
+C 64 ; WX 780 ; N at ; B 102 -17 802 698 ;
+C 65 ; WX 700 ; N A ; B -25 0 720 681 ;
+C 66 ; WX 720 ; N B ; B 21 0 746 681 ;
+C 67 ; WX 720 ; N C ; B 88 -17 746 698 ;
+C 68 ; WX 740 ; N D ; B 21 0 782 681 ;
+C 69 ; WX 680 ; N E ; B 21 0 736 681 ;
+C 70 ; WX 620 ; N F ; B 21 0 743 681 ;
+C 71 ; WX 760 ; N G ; B 88 -17 813 698 ;
+C 72 ; WX 800 ; N H ; B 21 0 888 681 ;
+C 73 ; WX 320 ; N I ; B 21 0 412 681 ;
+C 74 ; WX 560 ; N J ; B -2 -17 666 681 ;
+C 75 ; WX 720 ; N K ; B 21 0 804 681 ;
+C 76 ; WX 580 ; N L ; B 21 0 656 681 ;
+C 77 ; WX 860 ; N M ; B 18 0 956 681 ;
+C 78 ; WX 720 ; N N ; B 18 0 823 681 ;
+C 79 ; WX 760 ; N O ; B 88 -17 799 698 ;
+C 80 ; WX 600 ; N P ; B 21 0 681 681 ;
+C 81 ; WX 780 ; N Q ; B 61 -191 812 698 ;
+C 82 ; WX 700 ; N R ; B 21 0 736 681 ;
+C 83 ; WX 640 ; N S ; B 61 -17 668 698 ;
+C 84 ; WX 600 ; N T ; B 50 0 725 681 ;
+C 85 ; WX 720 ; N U ; B 118 -17 842 681 ;
+C 86 ; WX 680 ; N V ; B 87 0 815 681 ;
+C 87 ; WX 960 ; N W ; B 87 0 1095 681 ;
+C 88 ; WX 700 ; N X ; B -25 0 815 681 ;
+C 89 ; WX 660 ; N Y ; B 87 0 809 681 ;
+C 90 ; WX 580 ; N Z ; B 8 0 695 681 ;
+C 91 ; WX 260 ; N bracketleft ; B 56 -136 351 717 ;
+C 92 ; WX 600 ; N backslash ; B 84 0 542 717 ;
+C 93 ; WX 260 ; N bracketright ; B 15 -136 309 717 ;
+C 94 ; WX 600 ; N asciicircum ; B 97 276 599 681 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 280 ; N quoteleft ; B 191 470 330 698 ;
+C 97 ; WX 620 ; N a ; B 71 -8 686 494 ;
+C 98 ; WX 600 ; N b ; B 88 -8 621 717 ;
+C 99 ; WX 480 ; N c ; B 65 -8 522 494 ;
+C 100 ; WX 640 ; N d ; B 65 -8 695 717 ;
+C 101 ; WX 540 ; N e ; B 65 -8 575 494 ;
+C 102 ; WX 340 ; N f ; B -160 -218 557 725 ; L i fi ; L l fl ;
+C 103 ; WX 560 ; N g ; B 4 -221 581 494 ;
+C 104 ; WX 620 ; N h ; B 88 -8 689 717 ;
+C 105 ; WX 280 ; N i ; B 88 -8 351 663 ;
+C 106 ; WX 280 ; N j ; B -200 -221 308 663 ;
+C 107 ; WX 600 ; N k ; B 88 -8 657 717 ;
+C 108 ; WX 280 ; N l ; B 100 -8 342 717 ;
+C 109 ; WX 880 ; N m ; B 88 -8 952 494 ;
+C 110 ; WX 620 ; N n ; B 88 -8 673 494 ;
+C 111 ; WX 540 ; N o ; B 65 -8 572 494 ;
+C 112 ; WX 600 ; N p ; B -24 -212 620 494 ;
+C 113 ; WX 560 ; N q ; B 65 -212 584 494 ;
+C 114 ; WX 400 ; N r ; B 88 0 481 494 ;
+C 115 ; WX 540 ; N s ; B 65 -8 547 494 ;
+C 116 ; WX 340 ; N t ; B 88 -8 411 664 ;
+C 117 ; WX 620 ; N u ; B 88 -8 686 484 ;
+C 118 ; WX 540 ; N v ; B 88 -8 562 494 ;
+C 119 ; WX 880 ; N w ; B 88 -8 893 494 ;
+C 120 ; WX 540 ; N x ; B 9 -8 626 494 ;
+C 121 ; WX 600 ; N y ; B 60 -221 609 484 ;
+C 122 ; WX 520 ; N z ; B 38 -8 561 494 ;
+C 123 ; WX 360 ; N braceleft ; B 122 -191 442 717 ;
+C 124 ; WX 600 ; N bar ; B 294 -250 372 750 ;
+C 125 ; WX 380 ; N braceright ; B 13 -191 333 717 ;
+C 126 ; WX 600 ; N asciitilde ; B 91 207 595 386 ;
+C 161 ; WX 320 ; N exclamdown ; B 73 -213 301 494 ;
+C 162 ; WX 620 ; N cent ; B 148 -29 596 715 ;
+C 163 ; WX 620 ; N sterling ; B 4 -17 702 698 ;
+C 164 ; WX 20 ; N fraction ; B -228 0 323 681 ;
+C 165 ; WX 620 ; N yen ; B 71 0 735 681 ;
+C 166 ; WX 620 ; N florin ; B -26 -218 692 725 ;
+C 167 ; WX 620 ; N section ; B 38 -178 638 698 ;
+C 168 ; WX 620 ; N currency ; B 100 89 605 591 ;
+C 169 ; WX 200 ; N quotesingle ; B 99 473 247 698 ;
+C 170 ; WX 440 ; N quotedblleft ; B 191 470 493 698 ;
+C 171 ; WX 300 ; N guillemotleft ; B 70 129 313 434 ;
+C 172 ; WX 180 ; N guilsinglleft ; B 75 129 208 434 ;
+C 173 ; WX 180 ; N guilsinglright ; B 70 129 203 434 ;
+C 174 ; WX 640 ; N fi ; B -159 -222 709 725 ;
+C 175 ; WX 660 ; N fl ; B -159 -218 713 725 ;
+C 177 ; WX 500 ; N endash ; B 33 269 561 325 ;
+C 178 ; WX 620 ; N dagger ; B 192 -130 570 698 ;
+C 179 ; WX 620 ; N daggerdbl ; B 144 -122 566 698 ;
+C 180 ; WX 300 ; N periodcentered ; B 137 229 272 364 ;
+C 182 ; WX 620 ; N paragraph ; B 112 0 718 681 ;
+C 183 ; WX 460 ; N bullet ; B 100 170 444 511 ;
+C 184 ; WX 320 ; N quotesinglbase ; B 87 -114 226 113 ;
+C 185 ; WX 480 ; N quotedblbase ; B 87 -114 390 113 ;
+C 186 ; WX 440 ; N quotedblright ; B 148 470 451 698 ;
+C 187 ; WX 300 ; N guillemotright ; B 60 129 303 434 ;
+C 188 ; WX 1000 ; N ellipsis ; B 99 -8 900 127 ;
+C 189 ; WX 1180 ; N perthousand ; B 56 -8 1199 691 ;
+C 191 ; WX 540 ; N questiondown ; B 18 -212 508 494 ;
+C 193 ; WX 340 ; N grave ; B 182 551 377 706 ;
+C 194 ; WX 320 ; N acute ; B 178 551 373 706 ;
+C 195 ; WX 440 ; N circumflex ; B 176 571 479 685 ;
+C 196 ; WX 440 ; N tilde ; B 180 586 488 671 ;
+C 197 ; WX 440 ; N macron ; B 178 599 484 658 ;
+C 198 ; WX 440 ; N breve ; B 191 577 500 680 ;
+C 199 ; WX 260 ; N dotaccent ; B 169 543 290 664 ;
+C 200 ; WX 420 ; N dieresis ; B 185 569 467 688 ;
+C 202 ; WX 300 ; N ring ; B 178 551 334 706 ;
+C 203 ; WX 320 ; N cedilla ; B 45 -178 240 0 ;
+C 205 ; WX 340 ; N hungarumlaut ; B 167 547 402 738 ;
+C 206 ; WX 260 ; N ogonek ; B 51 -173 184 0 ;
+C 207 ; WX 440 ; N caron ; B 178 571 481 684 ;
+C 208 ; WX 1000 ; N emdash ; B 33 269 1061 325 ;
+C 225 ; WX 1220 ; N AE ; B -45 0 1269 681 ;
+C 227 ; WX 440 ; N ordfeminine ; B 130 396 513 698 ;
+C 232 ; WX 580 ; N Lslash ; B 21 0 656 681 ;
+C 233 ; WX 760 ; N Oslash ; B 88 -95 799 777 ;
+C 234 ; WX 1180 ; N OE ; B 88 -17 1237 698 ;
+C 235 ; WX 400 ; N ordmasculine ; B 139 396 455 698 ;
+C 241 ; WX 880 ; N ae ; B 71 -8 918 494 ;
+C 245 ; WX 280 ; N dotlessi ; B 88 -8 351 484 ;
+C 248 ; WX 340 ; N lslash ; B 50 -8 398 717 ;
+C 249 ; WX 540 ; N oslash ; B 65 -49 571 532 ;
+C 250 ; WX 900 ; N oe ; B 65 -8 948 494 ;
+C 251 ; WX 620 ; N germandbls ; B -121 -111 653 698 ;
+C -1 ; WX 540 ; N ecircumflex ; B 65 -8 575 685 ;
+C -1 ; WX 540 ; N edieresis ; B 65 -8 575 688 ;
+C -1 ; WX 620 ; N aacute ; B 71 -8 686 706 ;
+C -1 ; WX 740 ; N registered ; B 84 -17 784 698 ;
+C -1 ; WX 280 ; N icircumflex ; B 76 -8 379 685 ;
+C -1 ; WX 620 ; N udieresis ; B 88 -8 686 688 ;
+C -1 ; WX 540 ; N ograve ; B 65 -8 572 706 ;
+C -1 ; WX 620 ; N uacute ; B 88 -8 686 706 ;
+C -1 ; WX 620 ; N ucircumflex ; B 88 -8 686 685 ;
+C -1 ; WX 700 ; N Aacute ; B -25 0 720 883 ;
+C -1 ; WX 280 ; N igrave ; B 88 -8 351 706 ;
+C -1 ; WX 320 ; N Icircumflex ; B 21 0 449 862 ;
+C -1 ; WX 480 ; N ccedilla ; B 65 -178 522 494 ;
+C -1 ; WX 620 ; N adieresis ; B 71 -8 686 688 ;
+C -1 ; WX 680 ; N Ecircumflex ; B 21 0 736 862 ;
+C -1 ; WX 540 ; N scaron ; B 65 -8 547 684 ;
+C -1 ; WX 600 ; N thorn ; B -24 -212 620 717 ;
+C -1 ; WX 980 ; N trademark ; B 69 277 965 681 ;
+C -1 ; WX 540 ; N egrave ; B 65 -8 575 706 ;
+C -1 ; WX 372 ; N threesuperior ; B 70 269 439 698 ;
+C -1 ; WX 520 ; N zcaron ; B 38 -8 561 684 ;
+C -1 ; WX 620 ; N atilde ; B 71 -8 686 671 ;
+C -1 ; WX 620 ; N aring ; B 71 -8 686 706 ;
+C -1 ; WX 540 ; N ocircumflex ; B 65 -8 572 685 ;
+C -1 ; WX 680 ; N Edieresis ; B 21 0 736 865 ;
+C -1 ; WX 930 ; N threequarters ; B 99 0 913 691 ;
+C -1 ; WX 600 ; N ydieresis ; B 60 -221 609 688 ;
+C -1 ; WX 600 ; N yacute ; B 60 -221 609 706 ;
+C -1 ; WX 280 ; N iacute ; B 88 -8 351 706 ;
+C -1 ; WX 700 ; N Acircumflex ; B -25 0 720 862 ;
+C -1 ; WX 720 ; N Uacute ; B 118 -17 842 883 ;
+C -1 ; WX 540 ; N eacute ; B 65 -8 575 706 ;
+C -1 ; WX 760 ; N Ograve ; B 88 -17 799 883 ;
+C -1 ; WX 620 ; N agrave ; B 71 -8 686 706 ;
+C -1 ; WX 720 ; N Udieresis ; B 118 -17 842 865 ;
+C -1 ; WX 620 ; N acircumflex ; B 71 -8 686 685 ;
+C -1 ; WX 320 ; N Igrave ; B 21 0 412 883 ;
+C -1 ; WX 372 ; N twosuperior ; B 68 279 439 698 ;
+C -1 ; WX 720 ; N Ugrave ; B 118 -17 842 883 ;
+C -1 ; WX 930 ; N onequarter ; B 91 0 913 681 ;
+C -1 ; WX 720 ; N Ucircumflex ; B 118 -17 842 862 ;
+C -1 ; WX 640 ; N Scaron ; B 61 -17 668 861 ;
+C -1 ; WX 320 ; N Idieresis ; B 21 0 447 865 ;
+C -1 ; WX 280 ; N idieresis ; B 88 -8 377 688 ;
+C -1 ; WX 680 ; N Egrave ; B 21 0 736 883 ;
+C -1 ; WX 760 ; N Oacute ; B 88 -17 799 883 ;
+C -1 ; WX 600 ; N divide ; B 91 46 595 548 ;
+C -1 ; WX 700 ; N Atilde ; B -25 0 720 848 ;
+C -1 ; WX 700 ; N Aring ; B -25 0 720 883 ;
+C -1 ; WX 760 ; N Odieresis ; B 88 -17 799 865 ;
+C -1 ; WX 700 ; N Adieresis ; B -25 0 720 865 ;
+C -1 ; WX 720 ; N Ntilde ; B 18 0 823 848 ;
+C -1 ; WX 580 ; N Zcaron ; B 8 0 695 861 ;
+C -1 ; WX 600 ; N Thorn ; B 21 0 656 681 ;
+C -1 ; WX 320 ; N Iacute ; B 21 0 412 883 ;
+C -1 ; WX 600 ; N plusminus ; B 91 0 595 548 ;
+C -1 ; WX 600 ; N multiply ; B 91 44 595 548 ;
+C -1 ; WX 680 ; N Eacute ; B 21 0 736 883 ;
+C -1 ; WX 660 ; N Ydieresis ; B 87 0 809 865 ;
+C -1 ; WX 372 ; N onesuperior ; B 114 279 339 688 ;
+C -1 ; WX 620 ; N ugrave ; B 88 -8 686 706 ;
+C -1 ; WX 600 ; N logicalnot ; B 91 163 595 433 ;
+C -1 ; WX 620 ; N ntilde ; B 88 -8 673 671 ;
+C -1 ; WX 760 ; N Otilde ; B 88 -17 799 848 ;
+C -1 ; WX 540 ; N otilde ; B 65 -8 572 671 ;
+C -1 ; WX 720 ; N Ccedilla ; B 88 -178 746 698 ;
+C -1 ; WX 700 ; N Agrave ; B -25 0 720 883 ;
+C -1 ; WX 930 ; N onehalf ; B 91 0 925 681 ;
+C -1 ; WX 740 ; N Eth ; B 21 0 782 681 ;
+C -1 ; WX 400 ; N degree ; B 120 398 420 698 ;
+C -1 ; WX 660 ; N Yacute ; B 87 0 809 883 ;
+C -1 ; WX 760 ; N Ocircumflex ; B 88 -17 799 862 ;
+C -1 ; WX 540 ; N oacute ; B 65 -8 572 706 ;
+C -1 ; WX 620 ; N mu ; B 53 -221 686 484 ;
+C -1 ; WX 600 ; N minus ; B 91 259 595 335 ;
+C -1 ; WX 540 ; N eth ; B 65 -8 642 725 ;
+C -1 ; WX 540 ; N odieresis ; B 65 -8 572 688 ;
+C -1 ; WX 740 ; N copyright ; B 84 -17 784 698 ;
+C -1 ; WX 600 ; N brokenbar ; B 294 -175 372 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 85
+
+KPX A Y -62
+KPX A W -73
+KPX A V -78
+KPX A T -5
+
+KPX F period -97
+KPX F comma -98
+KPX F A -16
+
+KPX L y 20
+KPX L Y 7
+KPX L W 9
+KPX L V 4
+
+KPX P period -105
+KPX P comma -106
+KPX P A -30
+
+KPX R Y 11
+KPX R W 2
+KPX R V 2
+KPX R T 65
+
+KPX T semicolon 48
+KPX T s -7
+KPX T r 67
+KPX T period -78
+KPX T o 14
+KPX T i 71
+KPX T hyphen 20
+KPX T e 10
+KPX T comma -79
+KPX T colon 48
+KPX T c 16
+KPX T a 9
+KPX T A -14
+
+KPX V y -14
+KPX V u -10
+KPX V semicolon -44
+KPX V r -20
+KPX V period -100
+KPX V o -70
+KPX V i 3
+KPX V hyphen 20
+KPX V e -70
+KPX V comma -109
+KPX V colon -35
+KPX V a -70
+KPX V A -70
+
+KPX W y -14
+KPX W u -20
+KPX W semicolon -42
+KPX W r -30
+KPX W period -100
+KPX W o -60
+KPX W i 3
+KPX W hyphen 20
+KPX W e -60
+KPX W comma -109
+KPX W colon -35
+KPX W a -60
+KPX W A -60
+
+KPX Y v -19
+KPX Y u -31
+KPX Y semicolon -40
+KPX Y q -72
+KPX Y period -100
+KPX Y p -37
+KPX Y o -75
+KPX Y i -11
+KPX Y hyphen 20
+KPX Y e -78
+KPX Y comma -109
+KPX Y colon -35
+KPX Y a -79
+KPX Y A -82
+
+KPX f f -19
+
+KPX r q -14
+KPX r period -134
+KPX r o -10
+KPX r n 38
+KPX r m 37
+KPX r hyphen 20
+KPX r h -20
+KPX r g -3
+KPX r f -9
+KPX r e -15
+KPX r d -9
+KPX r comma -143
+KPX r c -8
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 200 177 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 130 177 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 140 177 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 160 177 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 220 177 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 130 177 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 210 177 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 140 177 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 150 177 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 150 177 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 30 177 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -30 177 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -20 177 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -30 177 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 130 177 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 250 177 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 190 177 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 200 177 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 210 177 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 190 177 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 100 177 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 230 177 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 170 177 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 180 177 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 170 177 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 200 177 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 140 177 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 70 177 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 120 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 70 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 80 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 110 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 140 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 60 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 90 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 30 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 40 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 80 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -40 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -100 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -90 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -60 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 60 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 80 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 20 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 40 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 80 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 30 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 30 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 120 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 60 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 70 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 110 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 140 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 70 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 20 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Courier-Bold.afm b/tlt3.0/library/afm/Courier-Bold.afm
new file mode 100644
index 0000000..4ade4fa
--- /dev/null
+++ b/tlt3.0/library/afm/Courier-Bold.afm
@@ -0,0 +1,345 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1989, 1990, 1991, Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Tue Sep 17 14:02:41 1991
+Comment UniqueID 36384
+Comment VMusage 31992 40360
+FontName Courier-Bold
+FullName Courier Bold
+FamilyName Courier
+Weight Bold
+ItalicAngle 0
+IsFixedPitch true
+FontBBox -113 -250 749 801
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.004
+Notice Copyright (c) 1989, 1990, 1991, Adobe Systems Incorporated. All rights reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 626
+Descender -142
+StartCharMetrics 260
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 202 -15 398 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 135 277 465 562 ;
+C 35 ; WX 600 ; N numbersign ; B 56 -45 544 651 ;
+C 36 ; WX 600 ; N dollar ; B 82 -126 519 666 ;
+C 37 ; WX 600 ; N percent ; B 5 -15 595 616 ;
+C 38 ; WX 600 ; N ampersand ; B 36 -15 546 543 ;
+C 39 ; WX 600 ; N quoteright ; B 171 277 423 562 ;
+C 40 ; WX 600 ; N parenleft ; B 219 -102 461 616 ;
+C 41 ; WX 600 ; N parenright ; B 139 -102 381 616 ;
+C 42 ; WX 600 ; N asterisk ; B 91 219 509 601 ;
+C 43 ; WX 600 ; N plus ; B 71 39 529 478 ;
+C 44 ; WX 600 ; N comma ; B 123 -111 393 174 ;
+C 45 ; WX 600 ; N hyphen ; B 100 203 500 313 ;
+C 46 ; WX 600 ; N period ; B 192 -15 408 171 ;
+C 47 ; WX 600 ; N slash ; B 98 -77 502 626 ;
+C 48 ; WX 600 ; N zero ; B 87 -15 513 616 ;
+C 49 ; WX 600 ; N one ; B 81 0 539 616 ;
+C 50 ; WX 600 ; N two ; B 61 0 499 616 ;
+C 51 ; WX 600 ; N three ; B 63 -15 501 616 ;
+C 52 ; WX 600 ; N four ; B 53 0 507 616 ;
+C 53 ; WX 600 ; N five ; B 70 -15 521 601 ;
+C 54 ; WX 600 ; N six ; B 90 -15 521 616 ;
+C 55 ; WX 600 ; N seven ; B 55 0 494 601 ;
+C 56 ; WX 600 ; N eight ; B 83 -15 517 616 ;
+C 57 ; WX 600 ; N nine ; B 79 -15 510 616 ;
+C 58 ; WX 600 ; N colon ; B 191 -15 407 425 ;
+C 59 ; WX 600 ; N semicolon ; B 123 -111 408 425 ;
+C 60 ; WX 600 ; N less ; B 66 15 523 501 ;
+C 61 ; WX 600 ; N equal ; B 71 118 529 398 ;
+C 62 ; WX 600 ; N greater ; B 77 15 534 501 ;
+C 63 ; WX 600 ; N question ; B 98 -14 501 580 ;
+C 64 ; WX 600 ; N at ; B 16 -15 584 616 ;
+C 65 ; WX 600 ; N A ; B -9 0 609 562 ;
+C 66 ; WX 600 ; N B ; B 30 0 573 562 ;
+C 67 ; WX 600 ; N C ; B 22 -18 560 580 ;
+C 68 ; WX 600 ; N D ; B 30 0 594 562 ;
+C 69 ; WX 600 ; N E ; B 25 0 560 562 ;
+C 70 ; WX 600 ; N F ; B 39 0 570 562 ;
+C 71 ; WX 600 ; N G ; B 22 -18 594 580 ;
+C 72 ; WX 600 ; N H ; B 20 0 580 562 ;
+C 73 ; WX 600 ; N I ; B 77 0 523 562 ;
+C 74 ; WX 600 ; N J ; B 37 -18 601 562 ;
+C 75 ; WX 600 ; N K ; B 21 0 599 562 ;
+C 76 ; WX 600 ; N L ; B 39 0 578 562 ;
+C 77 ; WX 600 ; N M ; B -2 0 602 562 ;
+C 78 ; WX 600 ; N N ; B 8 -12 610 562 ;
+C 79 ; WX 600 ; N O ; B 22 -18 578 580 ;
+C 80 ; WX 600 ; N P ; B 48 0 559 562 ;
+C 81 ; WX 600 ; N Q ; B 32 -138 578 580 ;
+C 82 ; WX 600 ; N R ; B 24 0 599 562 ;
+C 83 ; WX 600 ; N S ; B 47 -22 553 582 ;
+C 84 ; WX 600 ; N T ; B 21 0 579 562 ;
+C 85 ; WX 600 ; N U ; B 4 -18 596 562 ;
+C 86 ; WX 600 ; N V ; B -13 0 613 562 ;
+C 87 ; WX 600 ; N W ; B -18 0 618 562 ;
+C 88 ; WX 600 ; N X ; B 12 0 588 562 ;
+C 89 ; WX 600 ; N Y ; B 12 0 589 562 ;
+C 90 ; WX 600 ; N Z ; B 62 0 539 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 245 -102 475 616 ;
+C 92 ; WX 600 ; N backslash ; B 99 -77 503 626 ;
+C 93 ; WX 600 ; N bracketright ; B 125 -102 355 616 ;
+C 94 ; WX 600 ; N asciicircum ; B 108 250 492 616 ;
+C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 178 277 428 562 ;
+C 97 ; WX 600 ; N a ; B 35 -15 570 454 ;
+C 98 ; WX 600 ; N b ; B 0 -15 584 626 ;
+C 99 ; WX 600 ; N c ; B 40 -15 545 459 ;
+C 100 ; WX 600 ; N d ; B 20 -15 591 626 ;
+C 101 ; WX 600 ; N e ; B 40 -15 563 454 ;
+C 102 ; WX 600 ; N f ; B 83 0 547 626 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 30 -146 580 454 ;
+C 104 ; WX 600 ; N h ; B 5 0 592 626 ;
+C 105 ; WX 600 ; N i ; B 77 0 523 658 ;
+C 106 ; WX 600 ; N j ; B 63 -146 440 658 ;
+C 107 ; WX 600 ; N k ; B 20 0 585 626 ;
+C 108 ; WX 600 ; N l ; B 77 0 523 626 ;
+C 109 ; WX 600 ; N m ; B -22 0 626 454 ;
+C 110 ; WX 600 ; N n ; B 18 0 592 454 ;
+C 111 ; WX 600 ; N o ; B 30 -15 570 454 ;
+C 112 ; WX 600 ; N p ; B -1 -142 570 454 ;
+C 113 ; WX 600 ; N q ; B 20 -142 591 454 ;
+C 114 ; WX 600 ; N r ; B 47 0 580 454 ;
+C 115 ; WX 600 ; N s ; B 68 -17 535 459 ;
+C 116 ; WX 600 ; N t ; B 47 -15 532 562 ;
+C 117 ; WX 600 ; N u ; B -1 -15 569 439 ;
+C 118 ; WX 600 ; N v ; B -1 0 601 439 ;
+C 119 ; WX 600 ; N w ; B -18 0 618 439 ;
+C 120 ; WX 600 ; N x ; B 6 0 594 439 ;
+C 121 ; WX 600 ; N y ; B -4 -142 601 439 ;
+C 122 ; WX 600 ; N z ; B 81 0 520 439 ;
+C 123 ; WX 600 ; N braceleft ; B 160 -102 464 616 ;
+C 124 ; WX 600 ; N bar ; B 255 -250 345 750 ;
+C 125 ; WX 600 ; N braceright ; B 136 -102 440 616 ;
+C 126 ; WX 600 ; N asciitilde ; B 71 153 530 356 ;
+C 161 ; WX 600 ; N exclamdown ; B 202 -146 398 449 ;
+C 162 ; WX 600 ; N cent ; B 66 -49 518 614 ;
+C 163 ; WX 600 ; N sterling ; B 72 -28 558 611 ;
+C 164 ; WX 600 ; N fraction ; B 25 -60 576 661 ;
+C 165 ; WX 600 ; N yen ; B 10 0 590 562 ;
+C 166 ; WX 600 ; N florin ; B -30 -131 572 616 ;
+C 167 ; WX 600 ; N section ; B 83 -70 517 580 ;
+C 168 ; WX 600 ; N currency ; B 54 49 546 517 ;
+C 169 ; WX 600 ; N quotesingle ; B 227 277 373 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 71 277 535 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 8 70 553 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 141 70 459 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 141 70 459 446 ;
+C 174 ; WX 600 ; N fi ; B 12 0 593 626 ;
+C 175 ; WX 600 ; N fl ; B 12 0 593 626 ;
+C 177 ; WX 600 ; N endash ; B 65 203 535 313 ;
+C 178 ; WX 600 ; N dagger ; B 106 -70 494 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 106 -70 494 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 196 165 404 351 ;
+C 182 ; WX 600 ; N paragraph ; B 6 -70 576 580 ;
+C 183 ; WX 600 ; N bullet ; B 140 132 460 430 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 175 -142 427 143 ;
+C 185 ; WX 600 ; N quotedblbase ; B 65 -142 529 143 ;
+C 186 ; WX 600 ; N quotedblright ; B 61 277 525 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 47 70 592 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 26 -15 574 116 ;
+C 189 ; WX 600 ; N perthousand ; B -113 -15 713 616 ;
+C 191 ; WX 600 ; N questiondown ; B 99 -146 502 449 ;
+C 193 ; WX 600 ; N grave ; B 132 508 395 661 ;
+C 194 ; WX 600 ; N acute ; B 205 508 468 661 ;
+C 195 ; WX 600 ; N circumflex ; B 103 483 497 657 ;
+C 196 ; WX 600 ; N tilde ; B 89 493 512 636 ;
+C 197 ; WX 600 ; N macron ; B 88 505 512 585 ;
+C 198 ; WX 600 ; N breve ; B 83 468 517 631 ;
+C 199 ; WX 600 ; N dotaccent ; B 230 485 370 625 ;
+C 200 ; WX 600 ; N dieresis ; B 128 485 472 625 ;
+C 202 ; WX 600 ; N ring ; B 198 481 402 678 ;
+C 203 ; WX 600 ; N cedilla ; B 205 -206 387 0 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 68 488 588 661 ;
+C 206 ; WX 600 ; N ogonek ; B 169 -199 367 0 ;
+C 207 ; WX 600 ; N caron ; B 103 493 497 667 ;
+C 208 ; WX 600 ; N emdash ; B -10 203 610 313 ;
+C 225 ; WX 600 ; N AE ; B -29 0 602 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 147 196 453 580 ;
+C 232 ; WX 600 ; N Lslash ; B 39 0 578 562 ;
+C 233 ; WX 600 ; N Oslash ; B 22 -22 578 584 ;
+C 234 ; WX 600 ; N OE ; B -25 0 595 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 147 196 453 580 ;
+C 241 ; WX 600 ; N ae ; B -4 -15 601 454 ;
+C 245 ; WX 600 ; N dotlessi ; B 77 0 523 439 ;
+C 248 ; WX 600 ; N lslash ; B 77 0 523 626 ;
+C 249 ; WX 600 ; N oslash ; B 30 -24 570 463 ;
+C 250 ; WX 600 ; N oe ; B -18 -15 611 454 ;
+C 251 ; WX 600 ; N germandbls ; B 22 -15 596 626 ;
+C -1 ; WX 600 ; N Odieresis ; B 22 -18 578 748 ;
+C -1 ; WX 600 ; N logicalnot ; B 71 103 529 413 ;
+C -1 ; WX 600 ; N minus ; B 71 203 529 313 ;
+C -1 ; WX 600 ; N merge ; B 137 -15 464 487 ;
+C -1 ; WX 600 ; N degree ; B 86 243 474 616 ;
+C -1 ; WX 600 ; N dectab ; B 8 0 592 320 ;
+C -1 ; WX 600 ; N ll ; B -12 0 600 626 ;
+C -1 ; WX 600 ; N IJ ; B -8 -18 622 562 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 22 -18 578 780 ;
+C -1 ; WX 600 ; N ucircumflex ; B -1 -15 569 657 ;
+C -1 ; WX 600 ; N left ; B 65 44 535 371 ;
+C -1 ; WX 600 ; N threesuperior ; B 138 222 433 616 ;
+C -1 ; WX 600 ; N up ; B 136 0 463 447 ;
+C -1 ; WX 600 ; N multiply ; B 81 39 520 478 ;
+C -1 ; WX 600 ; N Scaron ; B 47 -22 553 790 ;
+C -1 ; WX 600 ; N tab ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 4 -18 596 780 ;
+C -1 ; WX 600 ; N divide ; B 71 16 529 500 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 609 780 ;
+C -1 ; WX 600 ; N eacute ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N uacute ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N twosuperior ; B 143 230 436 616 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 560 780 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 592 636 ;
+C -1 ; WX 600 ; N down ; B 137 -15 464 439 ;
+C -1 ; WX 600 ; N center ; B 40 14 560 580 ;
+C -1 ; WX 600 ; N onesuperior ; B 153 230 447 616 ;
+C -1 ; WX 600 ; N ij ; B 6 -146 574 658 ;
+C -1 ; WX 600 ; N edieresis ; B 40 -15 563 625 ;
+C -1 ; WX 600 ; N graybox ; B 76 0 525 599 ;
+C -1 ; WX 600 ; N odieresis ; B 30 -15 570 625 ;
+C -1 ; WX 600 ; N Ograve ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N threequarters ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N plusminus ; B 71 24 529 515 ;
+C -1 ; WX 600 ; N prescription ; B 24 -15 599 562 ;
+C -1 ; WX 600 ; N eth ; B 58 -27 543 626 ;
+C -1 ; WX 600 ; N largebullet ; B 248 229 352 333 ;
+C -1 ; WX 600 ; N egrave ; B 40 -15 563 661 ;
+C -1 ; WX 600 ; N ccedilla ; B 40 -206 545 459 ;
+C -1 ; WX 600 ; N notegraphic ; B 77 -15 523 572 ;
+C -1 ; WX 600 ; N Udieresis ; B 4 -18 596 748 ;
+C -1 ; WX 600 ; N Gcaron ; B 22 -18 594 790 ;
+C -1 ; WX 600 ; N arrowdown ; B 144 -15 456 608 ;
+C -1 ; WX 600 ; N format ; B 5 -146 115 601 ;
+C -1 ; WX 600 ; N Otilde ; B 22 -18 578 759 ;
+C -1 ; WX 600 ; N Idieresis ; B 77 0 523 748 ;
+C -1 ; WX 600 ; N adieresis ; B 35 -15 570 625 ;
+C -1 ; WX 600 ; N ecircumflex ; B 40 -15 563 657 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 594 562 ;
+C -1 ; WX 600 ; N onequarter ; B -56 -60 656 661 ;
+C -1 ; WX 600 ; N LL ; B -45 0 645 562 ;
+C -1 ; WX 600 ; N agrave ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 539 790 ;
+C -1 ; WX 600 ; N Scedilla ; B 47 -206 553 582 ;
+C -1 ; WX 600 ; N Idot ; B 77 0 523 748 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N indent ; B 65 45 535 372 ;
+C -1 ; WX 600 ; N Ugrave ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N scaron ; B 68 -17 535 667 ;
+C -1 ; WX 600 ; N overscore ; B 0 579 600 629 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 609 801 ;
+C -1 ; WX 600 ; N Ccedilla ; B 22 -206 560 580 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 523 784 ;
+C -1 ; WX 600 ; N brokenbar ; B 255 -175 345 675 ;
+C -1 ; WX 600 ; N Oacute ; B 22 -18 578 784 ;
+C -1 ; WX 600 ; N otilde ; B 30 -15 570 636 ;
+C -1 ; WX 600 ; N Yacute ; B 12 0 589 784 ;
+C -1 ; WX 600 ; N lira ; B 72 -28 558 611 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 523 780 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 609 759 ;
+C -1 ; WX 600 ; N Uacute ; B 4 -18 596 784 ;
+C -1 ; WX 600 ; N Ydieresis ; B 12 0 589 748 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -142 601 625 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 523 625 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 609 748 ;
+C -1 ; WX 600 ; N mu ; B -1 -142 569 439 ;
+C -1 ; WX 600 ; N trademark ; B -9 230 749 562 ;
+C -1 ; WX 600 ; N oacute ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N acircumflex ; B 35 -15 570 657 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 609 784 ;
+C -1 ; WX 600 ; N return ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N atilde ; B 35 -15 570 636 ;
+C -1 ; WX 600 ; N square ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N stop ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N udieresis ; B -1 -15 569 625 ;
+C -1 ; WX 600 ; N arrowup ; B 144 3 456 626 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 560 748 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 520 667 ;
+C -1 ; WX 600 ; N arrowboth ; B -24 143 624 455 ;
+C -1 ; WX 600 ; N gcaron ; B 30 -146 580 667 ;
+C -1 ; WX 600 ; N arrowleft ; B -24 143 634 455 ;
+C -1 ; WX 600 ; N aacute ; B 35 -15 570 661 ;
+C -1 ; WX 600 ; N ocircumflex ; B 30 -15 570 657 ;
+C -1 ; WX 600 ; N scedilla ; B 68 -206 535 459 ;
+C -1 ; WX 600 ; N ograve ; B 30 -15 570 661 ;
+C -1 ; WX 600 ; N onehalf ; B -47 -60 648 661 ;
+C -1 ; WX 600 ; N ugrave ; B -1 -15 569 661 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 610 759 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 523 661 ;
+C -1 ; WX 600 ; N arrowright ; B -34 143 624 455 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 557 562 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 560 784 ;
+C -1 ; WX 600 ; N thorn ; B -14 -142 570 626 ;
+C -1 ; WX 600 ; N aring ; B 35 -15 570 678 ;
+C -1 ; WX 600 ; N yacute ; B -4 -142 601 661 ;
+C -1 ; WX 600 ; N icircumflex ; B 63 0 523 657 ;
+EndCharMetrics
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 30 123 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -30 123 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -20 123 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave -50 123 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring -10 123 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde -30 123 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 30 123 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 0 123 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 0 123 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 0 123 ;
+CC Gcaron 2 ; PCC G 0 0 ; PCC caron 10 123 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 123 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 123 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 123 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 123 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 0 123 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 0 123 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 0 123 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 0 123 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 0 123 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 0 123 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 0 123 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 30 123 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 0 123 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 0 123 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave -30 123 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 30 123 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 0 123 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 0 123 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex -20 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis -10 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave -30 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ;
+CC gcaron 2 ; PCC g 0 0 ; PCC caron -40 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -40 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -40 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 0 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -20 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis -20 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 30 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 10 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 0 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Courier-BoldOblique.afm b/tlt3.0/library/afm/Courier-BoldOblique.afm
new file mode 100644
index 0000000..e0b3940
--- /dev/null
+++ b/tlt3.0/library/afm/Courier-BoldOblique.afm
@@ -0,0 +1,345 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1989, 1990, 1991, Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Tue Sep 17 14:13:24 1991
+Comment UniqueID 36389
+Comment VMusage 10055 54684
+FontName Courier-BoldOblique
+FullName Courier Bold Oblique
+FamilyName Courier
+Weight Bold
+ItalicAngle -12
+IsFixedPitch true
+FontBBox -56 -250 868 801
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.004
+Notice Copyright (c) 1989, 1990, 1991, Adobe Systems Incorporated. All rights reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 439
+Ascender 626
+Descender -142
+StartCharMetrics 260
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 216 -15 495 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 212 277 584 562 ;
+C 35 ; WX 600 ; N numbersign ; B 88 -45 640 651 ;
+C 36 ; WX 600 ; N dollar ; B 87 -126 629 666 ;
+C 37 ; WX 600 ; N percent ; B 102 -15 624 616 ;
+C 38 ; WX 600 ; N ampersand ; B 62 -15 594 543 ;
+C 39 ; WX 600 ; N quoteright ; B 230 277 542 562 ;
+C 40 ; WX 600 ; N parenleft ; B 266 -102 592 616 ;
+C 41 ; WX 600 ; N parenright ; B 117 -102 444 616 ;
+C 42 ; WX 600 ; N asterisk ; B 179 219 597 601 ;
+C 43 ; WX 600 ; N plus ; B 114 39 596 478 ;
+C 44 ; WX 600 ; N comma ; B 99 -111 430 174 ;
+C 45 ; WX 600 ; N hyphen ; B 143 203 567 313 ;
+C 46 ; WX 600 ; N period ; B 207 -15 426 171 ;
+C 47 ; WX 600 ; N slash ; B 91 -77 626 626 ;
+C 48 ; WX 600 ; N zero ; B 136 -15 592 616 ;
+C 49 ; WX 600 ; N one ; B 93 0 561 616 ;
+C 50 ; WX 600 ; N two ; B 61 0 593 616 ;
+C 51 ; WX 600 ; N three ; B 72 -15 571 616 ;
+C 52 ; WX 600 ; N four ; B 82 0 558 616 ;
+C 53 ; WX 600 ; N five ; B 77 -15 621 601 ;
+C 54 ; WX 600 ; N six ; B 136 -15 652 616 ;
+C 55 ; WX 600 ; N seven ; B 147 0 622 601 ;
+C 56 ; WX 600 ; N eight ; B 115 -15 604 616 ;
+C 57 ; WX 600 ; N nine ; B 76 -15 592 616 ;
+C 58 ; WX 600 ; N colon ; B 206 -15 479 425 ;
+C 59 ; WX 600 ; N semicolon ; B 99 -111 480 425 ;
+C 60 ; WX 600 ; N less ; B 121 15 612 501 ;
+C 61 ; WX 600 ; N equal ; B 96 118 614 398 ;
+C 62 ; WX 600 ; N greater ; B 97 15 589 501 ;
+C 63 ; WX 600 ; N question ; B 183 -14 591 580 ;
+C 64 ; WX 600 ; N at ; B 66 -15 641 616 ;
+C 65 ; WX 600 ; N A ; B -9 0 631 562 ;
+C 66 ; WX 600 ; N B ; B 30 0 629 562 ;
+C 67 ; WX 600 ; N C ; B 75 -18 674 580 ;
+C 68 ; WX 600 ; N D ; B 30 0 664 562 ;
+C 69 ; WX 600 ; N E ; B 25 0 669 562 ;
+C 70 ; WX 600 ; N F ; B 39 0 683 562 ;
+C 71 ; WX 600 ; N G ; B 75 -18 674 580 ;
+C 72 ; WX 600 ; N H ; B 20 0 699 562 ;
+C 73 ; WX 600 ; N I ; B 77 0 642 562 ;
+C 74 ; WX 600 ; N J ; B 59 -18 720 562 ;
+C 75 ; WX 600 ; N K ; B 21 0 691 562 ;
+C 76 ; WX 600 ; N L ; B 39 0 635 562 ;
+C 77 ; WX 600 ; N M ; B -2 0 721 562 ;
+C 78 ; WX 600 ; N N ; B 8 -12 729 562 ;
+C 79 ; WX 600 ; N O ; B 74 -18 645 580 ;
+C 80 ; WX 600 ; N P ; B 48 0 642 562 ;
+C 81 ; WX 600 ; N Q ; B 84 -138 636 580 ;
+C 82 ; WX 600 ; N R ; B 24 0 617 562 ;
+C 83 ; WX 600 ; N S ; B 54 -22 672 582 ;
+C 84 ; WX 600 ; N T ; B 86 0 678 562 ;
+C 85 ; WX 600 ; N U ; B 101 -18 715 562 ;
+C 86 ; WX 600 ; N V ; B 84 0 732 562 ;
+C 87 ; WX 600 ; N W ; B 84 0 737 562 ;
+C 88 ; WX 600 ; N X ; B 12 0 689 562 ;
+C 89 ; WX 600 ; N Y ; B 109 0 708 562 ;
+C 90 ; WX 600 ; N Z ; B 62 0 636 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 223 -102 606 616 ;
+C 92 ; WX 600 ; N backslash ; B 223 -77 496 626 ;
+C 93 ; WX 600 ; N bracketright ; B 103 -102 486 616 ;
+C 94 ; WX 600 ; N asciicircum ; B 171 250 555 616 ;
+C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 297 277 487 562 ;
+C 97 ; WX 600 ; N a ; B 62 -15 592 454 ;
+C 98 ; WX 600 ; N b ; B 13 -15 636 626 ;
+C 99 ; WX 600 ; N c ; B 81 -15 631 459 ;
+C 100 ; WX 600 ; N d ; B 61 -15 644 626 ;
+C 101 ; WX 600 ; N e ; B 81 -15 604 454 ;
+C 102 ; WX 600 ; N f ; B 83 0 677 626 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 41 -146 673 454 ;
+C 104 ; WX 600 ; N h ; B 18 0 614 626 ;
+C 105 ; WX 600 ; N i ; B 77 0 545 658 ;
+C 106 ; WX 600 ; N j ; B 37 -146 580 658 ;
+C 107 ; WX 600 ; N k ; B 33 0 642 626 ;
+C 108 ; WX 600 ; N l ; B 77 0 545 626 ;
+C 109 ; WX 600 ; N m ; B -22 0 648 454 ;
+C 110 ; WX 600 ; N n ; B 18 0 614 454 ;
+C 111 ; WX 600 ; N o ; B 71 -15 622 454 ;
+C 112 ; WX 600 ; N p ; B -31 -142 622 454 ;
+C 113 ; WX 600 ; N q ; B 61 -142 684 454 ;
+C 114 ; WX 600 ; N r ; B 47 0 654 454 ;
+C 115 ; WX 600 ; N s ; B 67 -17 607 459 ;
+C 116 ; WX 600 ; N t ; B 118 -15 566 562 ;
+C 117 ; WX 600 ; N u ; B 70 -15 591 439 ;
+C 118 ; WX 600 ; N v ; B 70 0 694 439 ;
+C 119 ; WX 600 ; N w ; B 53 0 711 439 ;
+C 120 ; WX 600 ; N x ; B 6 0 670 439 ;
+C 121 ; WX 600 ; N y ; B -20 -142 694 439 ;
+C 122 ; WX 600 ; N z ; B 81 0 613 439 ;
+C 123 ; WX 600 ; N braceleft ; B 204 -102 595 616 ;
+C 124 ; WX 600 ; N bar ; B 202 -250 504 750 ;
+C 125 ; WX 600 ; N braceright ; B 114 -102 506 616 ;
+C 126 ; WX 600 ; N asciitilde ; B 120 153 589 356 ;
+C 161 ; WX 600 ; N exclamdown ; B 197 -146 477 449 ;
+C 162 ; WX 600 ; N cent ; B 121 -49 604 614 ;
+C 163 ; WX 600 ; N sterling ; B 107 -28 650 611 ;
+C 164 ; WX 600 ; N fraction ; B 22 -60 707 661 ;
+C 165 ; WX 600 ; N yen ; B 98 0 709 562 ;
+C 166 ; WX 600 ; N florin ; B -56 -131 701 616 ;
+C 167 ; WX 600 ; N section ; B 74 -70 619 580 ;
+C 168 ; WX 600 ; N currency ; B 77 49 643 517 ;
+C 169 ; WX 600 ; N quotesingle ; B 304 277 492 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 190 277 594 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 63 70 638 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 196 70 544 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 166 70 514 446 ;
+C 174 ; WX 600 ; N fi ; B 12 0 643 626 ;
+C 175 ; WX 600 ; N fl ; B 12 0 643 626 ;
+C 177 ; WX 600 ; N endash ; B 108 203 602 313 ;
+C 178 ; WX 600 ; N dagger ; B 176 -70 586 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 122 -70 586 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 249 165 461 351 ;
+C 182 ; WX 600 ; N paragraph ; B 61 -70 699 580 ;
+C 183 ; WX 600 ; N bullet ; B 197 132 523 430 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 145 -142 457 143 ;
+C 185 ; WX 600 ; N quotedblbase ; B 35 -142 559 143 ;
+C 186 ; WX 600 ; N quotedblright ; B 120 277 644 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 72 70 647 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 35 -15 586 116 ;
+C 189 ; WX 600 ; N perthousand ; B -44 -15 742 616 ;
+C 191 ; WX 600 ; N questiondown ; B 101 -146 509 449 ;
+C 193 ; WX 600 ; N grave ; B 272 508 503 661 ;
+C 194 ; WX 600 ; N acute ; B 313 508 608 661 ;
+C 195 ; WX 600 ; N circumflex ; B 212 483 606 657 ;
+C 196 ; WX 600 ; N tilde ; B 200 493 642 636 ;
+C 197 ; WX 600 ; N macron ; B 195 505 636 585 ;
+C 198 ; WX 600 ; N breve ; B 217 468 651 631 ;
+C 199 ; WX 600 ; N dotaccent ; B 346 485 490 625 ;
+C 200 ; WX 600 ; N dieresis ; B 244 485 592 625 ;
+C 202 ; WX 600 ; N ring ; B 319 481 528 678 ;
+C 203 ; WX 600 ; N cedilla ; B 169 -206 367 0 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 172 488 728 661 ;
+C 206 ; WX 600 ; N ogonek ; B 144 -199 350 0 ;
+C 207 ; WX 600 ; N caron ; B 238 493 632 667 ;
+C 208 ; WX 600 ; N emdash ; B 33 203 677 313 ;
+C 225 ; WX 600 ; N AE ; B -29 0 707 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 189 196 526 580 ;
+C 232 ; WX 600 ; N Lslash ; B 39 0 635 562 ;
+C 233 ; WX 600 ; N Oslash ; B 48 -22 672 584 ;
+C 234 ; WX 600 ; N OE ; B 26 0 700 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 189 196 542 580 ;
+C 241 ; WX 600 ; N ae ; B 21 -15 651 454 ;
+C 245 ; WX 600 ; N dotlessi ; B 77 0 545 439 ;
+C 248 ; WX 600 ; N lslash ; B 77 0 578 626 ;
+C 249 ; WX 600 ; N oslash ; B 55 -24 637 463 ;
+C 250 ; WX 600 ; N oe ; B 19 -15 661 454 ;
+C 251 ; WX 600 ; N germandbls ; B 22 -15 628 626 ;
+C -1 ; WX 600 ; N Odieresis ; B 74 -18 645 748 ;
+C -1 ; WX 600 ; N logicalnot ; B 135 103 617 413 ;
+C -1 ; WX 600 ; N minus ; B 114 203 596 313 ;
+C -1 ; WX 600 ; N merge ; B 168 -15 533 487 ;
+C -1 ; WX 600 ; N degree ; B 173 243 569 616 ;
+C -1 ; WX 600 ; N dectab ; B 8 0 615 320 ;
+C -1 ; WX 600 ; N ll ; B 1 0 653 626 ;
+C -1 ; WX 600 ; N IJ ; B -8 -18 741 562 ;
+C -1 ; WX 600 ; N Eacute ; B 25 0 669 784 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 74 -18 645 780 ;
+C -1 ; WX 600 ; N ucircumflex ; B 70 -15 591 657 ;
+C -1 ; WX 600 ; N left ; B 109 44 589 371 ;
+C -1 ; WX 600 ; N threesuperior ; B 193 222 525 616 ;
+C -1 ; WX 600 ; N up ; B 196 0 523 447 ;
+C -1 ; WX 600 ; N multiply ; B 105 39 606 478 ;
+C -1 ; WX 600 ; N Scaron ; B 54 -22 672 790 ;
+C -1 ; WX 600 ; N tab ; B 19 0 641 562 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 101 -18 715 780 ;
+C -1 ; WX 600 ; N divide ; B 114 16 596 500 ;
+C -1 ; WX 600 ; N Acircumflex ; B -9 0 631 780 ;
+C -1 ; WX 600 ; N eacute ; B 81 -15 608 661 ;
+C -1 ; WX 600 ; N uacute ; B 70 -15 608 661 ;
+C -1 ; WX 600 ; N Aacute ; B -9 0 665 784 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N twosuperior ; B 192 230 541 616 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 25 0 669 780 ;
+C -1 ; WX 600 ; N ntilde ; B 18 0 642 636 ;
+C -1 ; WX 600 ; N down ; B 168 -15 496 439 ;
+C -1 ; WX 600 ; N center ; B 103 14 623 580 ;
+C -1 ; WX 600 ; N onesuperior ; B 213 230 514 616 ;
+C -1 ; WX 600 ; N ij ; B 6 -146 714 658 ;
+C -1 ; WX 600 ; N edieresis ; B 81 -15 604 625 ;
+C -1 ; WX 600 ; N graybox ; B 76 0 652 599 ;
+C -1 ; WX 600 ; N odieresis ; B 71 -15 622 625 ;
+C -1 ; WX 600 ; N Ograve ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -60 698 661 ;
+C -1 ; WX 600 ; N plusminus ; B 76 24 614 515 ;
+C -1 ; WX 600 ; N prescription ; B 24 -15 632 562 ;
+C -1 ; WX 600 ; N eth ; B 93 -27 661 626 ;
+C -1 ; WX 600 ; N largebullet ; B 307 229 413 333 ;
+C -1 ; WX 600 ; N egrave ; B 81 -15 604 661 ;
+C -1 ; WX 600 ; N ccedilla ; B 81 -206 631 459 ;
+C -1 ; WX 600 ; N notegraphic ; B 91 -15 619 572 ;
+C -1 ; WX 600 ; N Udieresis ; B 101 -18 715 748 ;
+C -1 ; WX 600 ; N Gcaron ; B 75 -18 674 790 ;
+C -1 ; WX 600 ; N arrowdown ; B 174 -15 486 608 ;
+C -1 ; WX 600 ; N format ; B -26 -146 243 601 ;
+C -1 ; WX 600 ; N Otilde ; B 74 -18 668 759 ;
+C -1 ; WX 600 ; N Idieresis ; B 77 0 642 748 ;
+C -1 ; WX 600 ; N adieresis ; B 62 -15 592 625 ;
+C -1 ; WX 600 ; N ecircumflex ; B 81 -15 606 657 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 664 562 ;
+C -1 ; WX 600 ; N onequarter ; B 14 -60 706 661 ;
+C -1 ; WX 600 ; N LL ; B -45 0 694 562 ;
+C -1 ; WX 600 ; N agrave ; B 62 -15 592 661 ;
+C -1 ; WX 600 ; N Zcaron ; B 62 0 659 790 ;
+C -1 ; WX 600 ; N Scedilla ; B 54 -206 672 582 ;
+C -1 ; WX 600 ; N Idot ; B 77 0 642 748 ;
+C -1 ; WX 600 ; N Iacute ; B 77 0 642 784 ;
+C -1 ; WX 600 ; N indent ; B 99 45 579 372 ;
+C -1 ; WX 600 ; N Ugrave ; B 101 -18 715 784 ;
+C -1 ; WX 600 ; N scaron ; B 67 -17 632 667 ;
+C -1 ; WX 600 ; N overscore ; B 123 579 734 629 ;
+C -1 ; WX 600 ; N Aring ; B -9 0 631 801 ;
+C -1 ; WX 600 ; N Ccedilla ; B 74 -206 674 580 ;
+C -1 ; WX 600 ; N Igrave ; B 77 0 642 784 ;
+C -1 ; WX 600 ; N brokenbar ; B 218 -175 488 675 ;
+C -1 ; WX 600 ; N Oacute ; B 74 -18 645 784 ;
+C -1 ; WX 600 ; N otilde ; B 71 -15 642 636 ;
+C -1 ; WX 600 ; N Yacute ; B 109 0 708 784 ;
+C -1 ; WX 600 ; N lira ; B 107 -28 650 611 ;
+C -1 ; WX 600 ; N Icircumflex ; B 77 0 642 780 ;
+C -1 ; WX 600 ; N Atilde ; B -9 0 638 759 ;
+C -1 ; WX 600 ; N Uacute ; B 101 -18 715 784 ;
+C -1 ; WX 600 ; N Ydieresis ; B 109 0 708 748 ;
+C -1 ; WX 600 ; N ydieresis ; B -20 -142 694 625 ;
+C -1 ; WX 600 ; N idieresis ; B 77 0 552 625 ;
+C -1 ; WX 600 ; N Adieresis ; B -9 0 631 748 ;
+C -1 ; WX 600 ; N mu ; B 50 -142 591 439 ;
+C -1 ; WX 600 ; N trademark ; B 86 230 868 562 ;
+C -1 ; WX 600 ; N oacute ; B 71 -15 622 661 ;
+C -1 ; WX 600 ; N acircumflex ; B 62 -15 592 657 ;
+C -1 ; WX 600 ; N Agrave ; B -9 0 631 784 ;
+C -1 ; WX 600 ; N return ; B 79 0 700 562 ;
+C -1 ; WX 600 ; N atilde ; B 62 -15 642 636 ;
+C -1 ; WX 600 ; N square ; B 19 0 700 562 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N stop ; B 19 0 700 562 ;
+C -1 ; WX 600 ; N udieresis ; B 70 -15 591 625 ;
+C -1 ; WX 600 ; N arrowup ; B 244 3 556 626 ;
+C -1 ; WX 600 ; N igrave ; B 77 0 545 661 ;
+C -1 ; WX 600 ; N Edieresis ; B 25 0 669 748 ;
+C -1 ; WX 600 ; N zcaron ; B 81 0 632 667 ;
+C -1 ; WX 600 ; N arrowboth ; B 40 143 688 455 ;
+C -1 ; WX 600 ; N gcaron ; B 41 -146 673 667 ;
+C -1 ; WX 600 ; N arrowleft ; B 40 143 708 455 ;
+C -1 ; WX 600 ; N aacute ; B 62 -15 608 661 ;
+C -1 ; WX 600 ; N ocircumflex ; B 71 -15 622 657 ;
+C -1 ; WX 600 ; N scedilla ; B 67 -206 607 459 ;
+C -1 ; WX 600 ; N ograve ; B 71 -15 622 661 ;
+C -1 ; WX 600 ; N onehalf ; B 23 -60 715 661 ;
+C -1 ; WX 600 ; N ugrave ; B 70 -15 591 661 ;
+C -1 ; WX 600 ; N Ntilde ; B 8 -12 729 759 ;
+C -1 ; WX 600 ; N iacute ; B 77 0 608 661 ;
+C -1 ; WX 600 ; N arrowright ; B 20 143 688 455 ;
+C -1 ; WX 600 ; N Thorn ; B 48 0 619 562 ;
+C -1 ; WX 600 ; N Egrave ; B 25 0 669 784 ;
+C -1 ; WX 600 ; N thorn ; B -31 -142 622 626 ;
+C -1 ; WX 600 ; N aring ; B 62 -15 592 678 ;
+C -1 ; WX 600 ; N yacute ; B -20 -142 694 661 ;
+C -1 ; WX 600 ; N icircumflex ; B 77 0 566 657 ;
+EndCharMetrics
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 56 123 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -4 123 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 6 123 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave -24 123 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 16 123 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde -4 123 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 56 123 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 26 123 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 26 123 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 26 123 ;
+CC Gcaron 2 ; PCC G 0 0 ; PCC caron 36 123 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 26 123 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 26 123 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 26 123 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 26 123 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 26 123 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 26 123 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 26 123 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 26 123 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 26 123 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 26 123 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 26 123 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 56 123 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 26 123 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 26 123 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave -4 123 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 56 123 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 26 123 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 26 123 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex -20 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis -10 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave -30 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ;
+CC gcaron 2 ; PCC g 0 0 ; PCC caron -40 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -40 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -40 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 0 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -20 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis -20 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 30 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 10 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 0 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Courier-Oblique.afm b/tlt3.0/library/afm/Courier-Oblique.afm
new file mode 100644
index 0000000..79bb0c3
--- /dev/null
+++ b/tlt3.0/library/afm/Courier-Oblique.afm
@@ -0,0 +1,345 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1989, 1990, 1991 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Tue Sep 17 09:42:19 1991
+Comment UniqueID 36350
+Comment VMusage 9174 52297
+FontName Courier-Oblique
+FullName Courier Oblique
+FamilyName Courier
+Weight Medium
+ItalicAngle -12
+IsFixedPitch true
+FontBBox -28 -250 742 805
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.004
+Notice Copyright (c) 1989, 1990, 1991 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StartCharMetrics 260
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 243 -15 464 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 273 328 532 562 ;
+C 35 ; WX 600 ; N numbersign ; B 133 -32 596 639 ;
+C 36 ; WX 600 ; N dollar ; B 108 -126 596 662 ;
+C 37 ; WX 600 ; N percent ; B 134 -15 599 622 ;
+C 38 ; WX 600 ; N ampersand ; B 87 -15 580 543 ;
+C 39 ; WX 600 ; N quoteright ; B 283 328 495 562 ;
+C 40 ; WX 600 ; N parenleft ; B 313 -108 572 622 ;
+C 41 ; WX 600 ; N parenright ; B 137 -108 396 622 ;
+C 42 ; WX 600 ; N asterisk ; B 212 257 580 607 ;
+C 43 ; WX 600 ; N plus ; B 129 44 580 470 ;
+C 44 ; WX 600 ; N comma ; B 157 -112 370 122 ;
+C 45 ; WX 600 ; N hyphen ; B 152 231 558 285 ;
+C 46 ; WX 600 ; N period ; B 238 -15 382 109 ;
+C 47 ; WX 600 ; N slash ; B 112 -80 604 629 ;
+C 48 ; WX 600 ; N zero ; B 154 -15 575 622 ;
+C 49 ; WX 600 ; N one ; B 98 0 515 622 ;
+C 50 ; WX 600 ; N two ; B 70 0 568 622 ;
+C 51 ; WX 600 ; N three ; B 82 -15 538 622 ;
+C 52 ; WX 600 ; N four ; B 108 0 541 622 ;
+C 53 ; WX 600 ; N five ; B 99 -15 589 607 ;
+C 54 ; WX 600 ; N six ; B 155 -15 629 622 ;
+C 55 ; WX 600 ; N seven ; B 182 0 612 607 ;
+C 56 ; WX 600 ; N eight ; B 132 -15 588 622 ;
+C 57 ; WX 600 ; N nine ; B 93 -15 574 622 ;
+C 58 ; WX 600 ; N colon ; B 238 -15 441 385 ;
+C 59 ; WX 600 ; N semicolon ; B 157 -112 441 385 ;
+C 60 ; WX 600 ; N less ; B 96 42 610 472 ;
+C 61 ; WX 600 ; N equal ; B 109 138 600 376 ;
+C 62 ; WX 600 ; N greater ; B 85 42 599 472 ;
+C 63 ; WX 600 ; N question ; B 222 -15 583 572 ;
+C 64 ; WX 600 ; N at ; B 127 -15 582 622 ;
+C 65 ; WX 600 ; N A ; B 3 0 607 562 ;
+C 66 ; WX 600 ; N B ; B 43 0 616 562 ;
+C 67 ; WX 600 ; N C ; B 93 -18 655 580 ;
+C 68 ; WX 600 ; N D ; B 43 0 645 562 ;
+C 69 ; WX 600 ; N E ; B 53 0 660 562 ;
+C 70 ; WX 600 ; N F ; B 53 0 660 562 ;
+C 71 ; WX 600 ; N G ; B 83 -18 645 580 ;
+C 72 ; WX 600 ; N H ; B 32 0 687 562 ;
+C 73 ; WX 600 ; N I ; B 96 0 623 562 ;
+C 74 ; WX 600 ; N J ; B 52 -18 685 562 ;
+C 75 ; WX 600 ; N K ; B 38 0 671 562 ;
+C 76 ; WX 600 ; N L ; B 47 0 607 562 ;
+C 77 ; WX 600 ; N M ; B 4 0 715 562 ;
+C 78 ; WX 600 ; N N ; B 7 -13 712 562 ;
+C 79 ; WX 600 ; N O ; B 94 -18 625 580 ;
+C 80 ; WX 600 ; N P ; B 79 0 644 562 ;
+C 81 ; WX 600 ; N Q ; B 95 -138 625 580 ;
+C 82 ; WX 600 ; N R ; B 38 0 598 562 ;
+C 83 ; WX 600 ; N S ; B 76 -20 650 580 ;
+C 84 ; WX 600 ; N T ; B 108 0 665 562 ;
+C 85 ; WX 600 ; N U ; B 125 -18 702 562 ;
+C 86 ; WX 600 ; N V ; B 105 -13 723 562 ;
+C 87 ; WX 600 ; N W ; B 106 -13 722 562 ;
+C 88 ; WX 600 ; N X ; B 23 0 675 562 ;
+C 89 ; WX 600 ; N Y ; B 133 0 695 562 ;
+C 90 ; WX 600 ; N Z ; B 86 0 610 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 246 -108 574 622 ;
+C 92 ; WX 600 ; N backslash ; B 249 -80 468 629 ;
+C 93 ; WX 600 ; N bracketright ; B 135 -108 463 622 ;
+C 94 ; WX 600 ; N asciicircum ; B 175 354 587 622 ;
+C 95 ; WX 600 ; N underscore ; B -27 -125 584 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 343 328 457 562 ;
+C 97 ; WX 600 ; N a ; B 76 -15 569 441 ;
+C 98 ; WX 600 ; N b ; B 29 -15 625 629 ;
+C 99 ; WX 600 ; N c ; B 106 -15 608 441 ;
+C 100 ; WX 600 ; N d ; B 85 -15 640 629 ;
+C 101 ; WX 600 ; N e ; B 106 -15 598 441 ;
+C 102 ; WX 600 ; N f ; B 114 0 662 629 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 61 -157 657 441 ;
+C 104 ; WX 600 ; N h ; B 33 0 592 629 ;
+C 105 ; WX 600 ; N i ; B 95 0 515 657 ;
+C 106 ; WX 600 ; N j ; B 52 -157 550 657 ;
+C 107 ; WX 600 ; N k ; B 58 0 633 629 ;
+C 108 ; WX 600 ; N l ; B 95 0 515 629 ;
+C 109 ; WX 600 ; N m ; B -5 0 615 441 ;
+C 110 ; WX 600 ; N n ; B 26 0 585 441 ;
+C 111 ; WX 600 ; N o ; B 102 -15 588 441 ;
+C 112 ; WX 600 ; N p ; B -24 -157 605 441 ;
+C 113 ; WX 600 ; N q ; B 85 -157 682 441 ;
+C 114 ; WX 600 ; N r ; B 60 0 636 441 ;
+C 115 ; WX 600 ; N s ; B 78 -15 584 441 ;
+C 116 ; WX 600 ; N t ; B 167 -15 561 561 ;
+C 117 ; WX 600 ; N u ; B 101 -15 572 426 ;
+C 118 ; WX 600 ; N v ; B 90 -10 681 426 ;
+C 119 ; WX 600 ; N w ; B 76 -10 695 426 ;
+C 120 ; WX 600 ; N x ; B 20 0 655 426 ;
+C 121 ; WX 600 ; N y ; B -4 -157 683 426 ;
+C 122 ; WX 600 ; N z ; B 99 0 593 426 ;
+C 123 ; WX 600 ; N braceleft ; B 233 -108 569 622 ;
+C 124 ; WX 600 ; N bar ; B 222 -250 485 750 ;
+C 125 ; WX 600 ; N braceright ; B 140 -108 477 622 ;
+C 126 ; WX 600 ; N asciitilde ; B 116 197 600 320 ;
+C 161 ; WX 600 ; N exclamdown ; B 225 -157 445 430 ;
+C 162 ; WX 600 ; N cent ; B 151 -49 588 614 ;
+C 163 ; WX 600 ; N sterling ; B 124 -21 621 611 ;
+C 164 ; WX 600 ; N fraction ; B 84 -57 646 665 ;
+C 165 ; WX 600 ; N yen ; B 120 0 693 562 ;
+C 166 ; WX 600 ; N florin ; B -26 -143 671 622 ;
+C 167 ; WX 600 ; N section ; B 104 -78 590 580 ;
+C 168 ; WX 600 ; N currency ; B 94 58 628 506 ;
+C 169 ; WX 600 ; N quotesingle ; B 345 328 460 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 262 328 541 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 92 70 652 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 204 70 540 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 170 70 506 446 ;
+C 174 ; WX 600 ; N fi ; B 3 0 619 629 ;
+C 175 ; WX 600 ; N fl ; B 3 0 619 629 ;
+C 177 ; WX 600 ; N endash ; B 124 231 586 285 ;
+C 178 ; WX 600 ; N dagger ; B 217 -78 546 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 163 -78 546 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 275 189 434 327 ;
+C 182 ; WX 600 ; N paragraph ; B 100 -78 630 562 ;
+C 183 ; WX 600 ; N bullet ; B 224 130 485 383 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 185 -134 397 100 ;
+C 185 ; WX 600 ; N quotedblbase ; B 115 -134 478 100 ;
+C 186 ; WX 600 ; N quotedblright ; B 213 328 576 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 58 70 618 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 46 -15 575 111 ;
+C 189 ; WX 600 ; N perthousand ; B 59 -15 627 622 ;
+C 191 ; WX 600 ; N questiondown ; B 105 -157 466 430 ;
+C 193 ; WX 600 ; N grave ; B 294 497 484 672 ;
+C 194 ; WX 600 ; N acute ; B 348 497 612 672 ;
+C 195 ; WX 600 ; N circumflex ; B 229 477 581 654 ;
+C 196 ; WX 600 ; N tilde ; B 212 489 629 606 ;
+C 197 ; WX 600 ; N macron ; B 232 525 600 565 ;
+C 198 ; WX 600 ; N breve ; B 279 501 576 609 ;
+C 199 ; WX 600 ; N dotaccent ; B 360 477 466 580 ;
+C 200 ; WX 600 ; N dieresis ; B 262 492 570 595 ;
+C 202 ; WX 600 ; N ring ; B 332 463 500 627 ;
+C 203 ; WX 600 ; N cedilla ; B 197 -151 344 10 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 239 497 683 672 ;
+C 206 ; WX 600 ; N ogonek ; B 207 -151 348 0 ;
+C 207 ; WX 600 ; N caron ; B 262 492 614 669 ;
+C 208 ; WX 600 ; N emdash ; B 49 231 661 285 ;
+C 225 ; WX 600 ; N AE ; B 3 0 655 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 209 249 512 580 ;
+C 232 ; WX 600 ; N Lslash ; B 47 0 607 562 ;
+C 233 ; WX 600 ; N Oslash ; B 94 -80 625 629 ;
+C 234 ; WX 600 ; N OE ; B 59 0 672 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 210 249 535 580 ;
+C 241 ; WX 600 ; N ae ; B 41 -15 626 441 ;
+C 245 ; WX 600 ; N dotlessi ; B 95 0 515 426 ;
+C 248 ; WX 600 ; N lslash ; B 95 0 583 629 ;
+C 249 ; WX 600 ; N oslash ; B 102 -80 588 506 ;
+C 250 ; WX 600 ; N oe ; B 54 -15 615 441 ;
+C 251 ; WX 600 ; N germandbls ; B 48 -15 617 629 ;
+C -1 ; WX 600 ; N Odieresis ; B 94 -18 625 731 ;
+C -1 ; WX 600 ; N logicalnot ; B 155 108 591 369 ;
+C -1 ; WX 600 ; N minus ; B 129 232 580 283 ;
+C -1 ; WX 600 ; N merge ; B 187 -15 503 436 ;
+C -1 ; WX 600 ; N degree ; B 214 269 576 622 ;
+C -1 ; WX 600 ; N dectab ; B 18 0 593 227 ;
+C -1 ; WX 600 ; N ll ; B 33 0 616 629 ;
+C -1 ; WX 600 ; N IJ ; B 32 -18 702 562 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 668 793 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 94 -18 625 775 ;
+C -1 ; WX 600 ; N ucircumflex ; B 101 -15 572 654 ;
+C -1 ; WX 600 ; N left ; B 114 68 580 348 ;
+C -1 ; WX 600 ; N threesuperior ; B 213 240 501 622 ;
+C -1 ; WX 600 ; N up ; B 223 0 503 437 ;
+C -1 ; WX 600 ; N multiply ; B 103 43 607 470 ;
+C -1 ; WX 600 ; N Scaron ; B 76 -20 673 805 ;
+C -1 ; WX 600 ; N tab ; B 19 0 641 562 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 125 -18 702 775 ;
+C -1 ; WX 600 ; N divide ; B 136 48 573 467 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 607 775 ;
+C -1 ; WX 600 ; N eacute ; B 106 -15 612 672 ;
+C -1 ; WX 600 ; N uacute ; B 101 -15 602 672 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 658 793 ;
+C -1 ; WX 600 ; N copyright ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N twosuperior ; B 230 249 535 622 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 660 775 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 629 606 ;
+C -1 ; WX 600 ; N down ; B 187 -15 467 426 ;
+C -1 ; WX 600 ; N center ; B 103 14 623 580 ;
+C -1 ; WX 600 ; N onesuperior ; B 231 249 491 622 ;
+C -1 ; WX 600 ; N ij ; B 37 -157 630 657 ;
+C -1 ; WX 600 ; N edieresis ; B 106 -15 598 595 ;
+C -1 ; WX 600 ; N graybox ; B 76 0 652 599 ;
+C -1 ; WX 600 ; N odieresis ; B 102 -15 588 595 ;
+C -1 ; WX 600 ; N Ograve ; B 94 -18 625 793 ;
+C -1 ; WX 600 ; N threequarters ; B 73 -56 659 666 ;
+C -1 ; WX 600 ; N plusminus ; B 96 44 594 558 ;
+C -1 ; WX 600 ; N prescription ; B 27 -15 617 562 ;
+C -1 ; WX 600 ; N eth ; B 102 -15 639 629 ;
+C -1 ; WX 600 ; N largebullet ; B 315 220 395 297 ;
+C -1 ; WX 600 ; N egrave ; B 106 -15 598 672 ;
+C -1 ; WX 600 ; N ccedilla ; B 106 -151 614 441 ;
+C -1 ; WX 600 ; N notegraphic ; B 143 -15 564 572 ;
+C -1 ; WX 600 ; N Udieresis ; B 125 -18 702 731 ;
+C -1 ; WX 600 ; N Gcaron ; B 83 -18 645 805 ;
+C -1 ; WX 600 ; N arrowdown ; B 152 -15 520 608 ;
+C -1 ; WX 600 ; N format ; B -28 -157 185 607 ;
+C -1 ; WX 600 ; N Otilde ; B 94 -18 656 732 ;
+C -1 ; WX 600 ; N Idieresis ; B 96 0 623 731 ;
+C -1 ; WX 600 ; N adieresis ; B 76 -15 570 595 ;
+C -1 ; WX 600 ; N ecircumflex ; B 106 -15 598 654 ;
+C -1 ; WX 600 ; N Eth ; B 43 0 645 562 ;
+C -1 ; WX 600 ; N onequarter ; B 65 -57 674 665 ;
+C -1 ; WX 600 ; N LL ; B 8 0 647 562 ;
+C -1 ; WX 600 ; N agrave ; B 76 -15 569 672 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 643 805 ;
+C -1 ; WX 600 ; N Scedilla ; B 76 -151 650 580 ;
+C -1 ; WX 600 ; N Idot ; B 96 0 623 716 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 638 793 ;
+C -1 ; WX 600 ; N indent ; B 108 68 574 348 ;
+C -1 ; WX 600 ; N Ugrave ; B 125 -18 702 793 ;
+C -1 ; WX 600 ; N scaron ; B 78 -15 614 669 ;
+C -1 ; WX 600 ; N overscore ; B 123 579 734 629 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 607 753 ;
+C -1 ; WX 600 ; N Ccedilla ; B 93 -151 658 580 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 623 793 ;
+C -1 ; WX 600 ; N brokenbar ; B 238 -175 469 675 ;
+C -1 ; WX 600 ; N Oacute ; B 94 -18 638 793 ;
+C -1 ; WX 600 ; N otilde ; B 102 -15 629 606 ;
+C -1 ; WX 600 ; N Yacute ; B 133 0 695 793 ;
+C -1 ; WX 600 ; N lira ; B 118 -21 621 611 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 623 775 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 656 732 ;
+C -1 ; WX 600 ; N Uacute ; B 125 -18 702 793 ;
+C -1 ; WX 600 ; N Ydieresis ; B 133 0 695 731 ;
+C -1 ; WX 600 ; N ydieresis ; B -4 -157 683 595 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 540 595 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 607 731 ;
+C -1 ; WX 600 ; N mu ; B 72 -157 572 426 ;
+C -1 ; WX 600 ; N trademark ; B 75 263 742 562 ;
+C -1 ; WX 600 ; N oacute ; B 102 -15 612 672 ;
+C -1 ; WX 600 ; N acircumflex ; B 76 -15 581 654 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 607 793 ;
+C -1 ; WX 600 ; N return ; B 79 0 700 562 ;
+C -1 ; WX 600 ; N atilde ; B 76 -15 629 606 ;
+C -1 ; WX 600 ; N square ; B 19 0 700 562 ;
+C -1 ; WX 600 ; N registered ; B 53 -18 667 580 ;
+C -1 ; WX 600 ; N stop ; B 19 0 700 562 ;
+C -1 ; WX 600 ; N udieresis ; B 101 -15 572 595 ;
+C -1 ; WX 600 ; N arrowup ; B 209 0 577 623 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 515 672 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 660 731 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 624 669 ;
+C -1 ; WX 600 ; N arrowboth ; B 36 115 692 483 ;
+C -1 ; WX 600 ; N gcaron ; B 61 -157 657 669 ;
+C -1 ; WX 600 ; N arrowleft ; B 40 115 693 483 ;
+C -1 ; WX 600 ; N aacute ; B 76 -15 612 672 ;
+C -1 ; WX 600 ; N ocircumflex ; B 102 -15 588 654 ;
+C -1 ; WX 600 ; N scedilla ; B 78 -151 584 441 ;
+C -1 ; WX 600 ; N ograve ; B 102 -15 588 672 ;
+C -1 ; WX 600 ; N onehalf ; B 65 -57 669 665 ;
+C -1 ; WX 600 ; N ugrave ; B 101 -15 572 672 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 712 732 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 612 672 ;
+C -1 ; WX 600 ; N arrowright ; B 34 115 688 483 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 606 562 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 660 793 ;
+C -1 ; WX 600 ; N thorn ; B -24 -157 605 629 ;
+C -1 ; WX 600 ; N aring ; B 76 -15 569 627 ;
+C -1 ; WX 600 ; N yacute ; B -4 -157 683 672 ;
+C -1 ; WX 600 ; N icircumflex ; B 95 0 551 654 ;
+EndCharMetrics
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 46 121 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -4 121 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -1 136 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave -4 121 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 12 126 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 27 126 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 56 121 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 26 121 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 29 136 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 26 121 ;
+CC Gcaron 2 ; PCC G 0 0 ; PCC caron 29 136 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 26 121 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 26 121 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 29 136 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 26 121 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 27 126 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 26 121 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 26 121 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 29 136 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 26 121 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 27 126 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 59 136 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 56 121 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 26 121 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 29 136 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave -4 121 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 56 121 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 29 136 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 29 136 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 0 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 0 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 0 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ;
+CC gcaron 2 ; PCC g 0 0 ; PCC caron -30 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -30 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -30 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -30 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute -10 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -10 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 0 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute -20 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis -10 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 10 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Courier.afm b/tlt3.0/library/afm/Courier.afm
new file mode 100644
index 0000000..e65ecdf
--- /dev/null
+++ b/tlt3.0/library/afm/Courier.afm
@@ -0,0 +1,345 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1989, 1990, 1991 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Tue Sep 17 07:47:21 1991
+Comment UniqueID 36347
+Comment VMusage 31037 39405
+FontName Courier
+FullName Courier
+FamilyName Courier
+Weight Medium
+ItalicAngle 0
+IsFixedPitch true
+FontBBox -28 -250 628 805
+UnderlinePosition -100
+UnderlineThickness 50
+Version 002.004
+Notice Copyright (c) 1989, 1990, 1991 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 562
+XHeight 426
+Ascender 629
+Descender -157
+StartCharMetrics 260
+C 32 ; WX 600 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 600 ; N exclam ; B 236 -15 364 572 ;
+C 34 ; WX 600 ; N quotedbl ; B 187 328 413 562 ;
+C 35 ; WX 600 ; N numbersign ; B 93 -32 507 639 ;
+C 36 ; WX 600 ; N dollar ; B 105 -126 496 662 ;
+C 37 ; WX 600 ; N percent ; B 81 -15 518 622 ;
+C 38 ; WX 600 ; N ampersand ; B 63 -15 538 543 ;
+C 39 ; WX 600 ; N quoteright ; B 213 328 376 562 ;
+C 40 ; WX 600 ; N parenleft ; B 269 -108 440 622 ;
+C 41 ; WX 600 ; N parenright ; B 160 -108 331 622 ;
+C 42 ; WX 600 ; N asterisk ; B 116 257 484 607 ;
+C 43 ; WX 600 ; N plus ; B 80 44 520 470 ;
+C 44 ; WX 600 ; N comma ; B 181 -112 344 122 ;
+C 45 ; WX 600 ; N hyphen ; B 103 231 497 285 ;
+C 46 ; WX 600 ; N period ; B 229 -15 371 109 ;
+C 47 ; WX 600 ; N slash ; B 125 -80 475 629 ;
+C 48 ; WX 600 ; N zero ; B 106 -15 494 622 ;
+C 49 ; WX 600 ; N one ; B 96 0 505 622 ;
+C 50 ; WX 600 ; N two ; B 70 0 471 622 ;
+C 51 ; WX 600 ; N three ; B 75 -15 466 622 ;
+C 52 ; WX 600 ; N four ; B 78 0 500 622 ;
+C 53 ; WX 600 ; N five ; B 92 -15 497 607 ;
+C 54 ; WX 600 ; N six ; B 111 -15 497 622 ;
+C 55 ; WX 600 ; N seven ; B 82 0 483 607 ;
+C 56 ; WX 600 ; N eight ; B 102 -15 498 622 ;
+C 57 ; WX 600 ; N nine ; B 96 -15 489 622 ;
+C 58 ; WX 600 ; N colon ; B 229 -15 371 385 ;
+C 59 ; WX 600 ; N semicolon ; B 181 -112 371 385 ;
+C 60 ; WX 600 ; N less ; B 41 42 519 472 ;
+C 61 ; WX 600 ; N equal ; B 80 138 520 376 ;
+C 62 ; WX 600 ; N greater ; B 66 42 544 472 ;
+C 63 ; WX 600 ; N question ; B 129 -15 492 572 ;
+C 64 ; WX 600 ; N at ; B 77 -15 533 622 ;
+C 65 ; WX 600 ; N A ; B 3 0 597 562 ;
+C 66 ; WX 600 ; N B ; B 43 0 559 562 ;
+C 67 ; WX 600 ; N C ; B 41 -18 540 580 ;
+C 68 ; WX 600 ; N D ; B 43 0 574 562 ;
+C 69 ; WX 600 ; N E ; B 53 0 550 562 ;
+C 70 ; WX 600 ; N F ; B 53 0 545 562 ;
+C 71 ; WX 600 ; N G ; B 31 -18 575 580 ;
+C 72 ; WX 600 ; N H ; B 32 0 568 562 ;
+C 73 ; WX 600 ; N I ; B 96 0 504 562 ;
+C 74 ; WX 600 ; N J ; B 34 -18 566 562 ;
+C 75 ; WX 600 ; N K ; B 38 0 582 562 ;
+C 76 ; WX 600 ; N L ; B 47 0 554 562 ;
+C 77 ; WX 600 ; N M ; B 4 0 596 562 ;
+C 78 ; WX 600 ; N N ; B 7 -13 593 562 ;
+C 79 ; WX 600 ; N O ; B 43 -18 557 580 ;
+C 80 ; WX 600 ; N P ; B 79 0 558 562 ;
+C 81 ; WX 600 ; N Q ; B 43 -138 557 580 ;
+C 82 ; WX 600 ; N R ; B 38 0 588 562 ;
+C 83 ; WX 600 ; N S ; B 72 -20 529 580 ;
+C 84 ; WX 600 ; N T ; B 38 0 563 562 ;
+C 85 ; WX 600 ; N U ; B 17 -18 583 562 ;
+C 86 ; WX 600 ; N V ; B -4 -13 604 562 ;
+C 87 ; WX 600 ; N W ; B -3 -13 603 562 ;
+C 88 ; WX 600 ; N X ; B 23 0 577 562 ;
+C 89 ; WX 600 ; N Y ; B 24 0 576 562 ;
+C 90 ; WX 600 ; N Z ; B 86 0 514 562 ;
+C 91 ; WX 600 ; N bracketleft ; B 269 -108 442 622 ;
+C 92 ; WX 600 ; N backslash ; B 118 -80 482 629 ;
+C 93 ; WX 600 ; N bracketright ; B 158 -108 331 622 ;
+C 94 ; WX 600 ; N asciicircum ; B 94 354 506 622 ;
+C 95 ; WX 600 ; N underscore ; B 0 -125 600 -75 ;
+C 96 ; WX 600 ; N quoteleft ; B 224 328 387 562 ;
+C 97 ; WX 600 ; N a ; B 53 -15 559 441 ;
+C 98 ; WX 600 ; N b ; B 14 -15 575 629 ;
+C 99 ; WX 600 ; N c ; B 66 -15 529 441 ;
+C 100 ; WX 600 ; N d ; B 45 -15 591 629 ;
+C 101 ; WX 600 ; N e ; B 66 -15 548 441 ;
+C 102 ; WX 600 ; N f ; B 114 0 531 629 ; L i fi ; L l fl ;
+C 103 ; WX 600 ; N g ; B 45 -157 566 441 ;
+C 104 ; WX 600 ; N h ; B 18 0 582 629 ;
+C 105 ; WX 600 ; N i ; B 95 0 505 657 ;
+C 106 ; WX 600 ; N j ; B 82 -157 410 657 ;
+C 107 ; WX 600 ; N k ; B 43 0 580 629 ;
+C 108 ; WX 600 ; N l ; B 95 0 505 629 ;
+C 109 ; WX 600 ; N m ; B -5 0 605 441 ;
+C 110 ; WX 600 ; N n ; B 26 0 575 441 ;
+C 111 ; WX 600 ; N o ; B 62 -15 538 441 ;
+C 112 ; WX 600 ; N p ; B 9 -157 555 441 ;
+C 113 ; WX 600 ; N q ; B 45 -157 591 441 ;
+C 114 ; WX 600 ; N r ; B 60 0 559 441 ;
+C 115 ; WX 600 ; N s ; B 80 -15 513 441 ;
+C 116 ; WX 600 ; N t ; B 87 -15 530 561 ;
+C 117 ; WX 600 ; N u ; B 21 -15 562 426 ;
+C 118 ; WX 600 ; N v ; B 10 -10 590 426 ;
+C 119 ; WX 600 ; N w ; B -4 -10 604 426 ;
+C 120 ; WX 600 ; N x ; B 20 0 580 426 ;
+C 121 ; WX 600 ; N y ; B 7 -157 592 426 ;
+C 122 ; WX 600 ; N z ; B 99 0 502 426 ;
+C 123 ; WX 600 ; N braceleft ; B 182 -108 437 622 ;
+C 124 ; WX 600 ; N bar ; B 275 -250 326 750 ;
+C 125 ; WX 600 ; N braceright ; B 163 -108 418 622 ;
+C 126 ; WX 600 ; N asciitilde ; B 63 197 540 320 ;
+C 161 ; WX 600 ; N exclamdown ; B 236 -157 364 430 ;
+C 162 ; WX 600 ; N cent ; B 96 -49 500 614 ;
+C 163 ; WX 600 ; N sterling ; B 84 -21 521 611 ;
+C 164 ; WX 600 ; N fraction ; B 92 -57 509 665 ;
+C 165 ; WX 600 ; N yen ; B 26 0 574 562 ;
+C 166 ; WX 600 ; N florin ; B 4 -143 539 622 ;
+C 167 ; WX 600 ; N section ; B 113 -78 488 580 ;
+C 168 ; WX 600 ; N currency ; B 73 58 527 506 ;
+C 169 ; WX 600 ; N quotesingle ; B 259 328 341 562 ;
+C 170 ; WX 600 ; N quotedblleft ; B 143 328 471 562 ;
+C 171 ; WX 600 ; N guillemotleft ; B 37 70 563 446 ;
+C 172 ; WX 600 ; N guilsinglleft ; B 149 70 451 446 ;
+C 173 ; WX 600 ; N guilsinglright ; B 149 70 451 446 ;
+C 174 ; WX 600 ; N fi ; B 3 0 597 629 ;
+C 175 ; WX 600 ; N fl ; B 3 0 597 629 ;
+C 177 ; WX 600 ; N endash ; B 75 231 525 285 ;
+C 178 ; WX 600 ; N dagger ; B 141 -78 459 580 ;
+C 179 ; WX 600 ; N daggerdbl ; B 141 -78 459 580 ;
+C 180 ; WX 600 ; N periodcentered ; B 222 189 378 327 ;
+C 182 ; WX 600 ; N paragraph ; B 50 -78 511 562 ;
+C 183 ; WX 600 ; N bullet ; B 172 130 428 383 ;
+C 184 ; WX 600 ; N quotesinglbase ; B 213 -134 376 100 ;
+C 185 ; WX 600 ; N quotedblbase ; B 143 -134 457 100 ;
+C 186 ; WX 600 ; N quotedblright ; B 143 328 457 562 ;
+C 187 ; WX 600 ; N guillemotright ; B 37 70 563 446 ;
+C 188 ; WX 600 ; N ellipsis ; B 37 -15 563 111 ;
+C 189 ; WX 600 ; N perthousand ; B 3 -15 600 622 ;
+C 191 ; WX 600 ; N questiondown ; B 108 -157 471 430 ;
+C 193 ; WX 600 ; N grave ; B 151 497 378 672 ;
+C 194 ; WX 600 ; N acute ; B 242 497 469 672 ;
+C 195 ; WX 600 ; N circumflex ; B 124 477 476 654 ;
+C 196 ; WX 600 ; N tilde ; B 105 489 503 606 ;
+C 197 ; WX 600 ; N macron ; B 120 525 480 565 ;
+C 198 ; WX 600 ; N breve ; B 153 501 447 609 ;
+C 199 ; WX 600 ; N dotaccent ; B 249 477 352 580 ;
+C 200 ; WX 600 ; N dieresis ; B 148 492 453 595 ;
+C 202 ; WX 600 ; N ring ; B 218 463 382 627 ;
+C 203 ; WX 600 ; N cedilla ; B 224 -151 362 10 ;
+C 205 ; WX 600 ; N hungarumlaut ; B 133 497 540 672 ;
+C 206 ; WX 600 ; N ogonek ; B 227 -151 370 0 ;
+C 207 ; WX 600 ; N caron ; B 124 492 476 669 ;
+C 208 ; WX 600 ; N emdash ; B 0 231 600 285 ;
+C 225 ; WX 600 ; N AE ; B 3 0 550 562 ;
+C 227 ; WX 600 ; N ordfeminine ; B 156 249 442 580 ;
+C 232 ; WX 600 ; N Lslash ; B 47 0 554 562 ;
+C 233 ; WX 600 ; N Oslash ; B 43 -80 557 629 ;
+C 234 ; WX 600 ; N OE ; B 7 0 567 562 ;
+C 235 ; WX 600 ; N ordmasculine ; B 157 249 443 580 ;
+C 241 ; WX 600 ; N ae ; B 19 -15 570 441 ;
+C 245 ; WX 600 ; N dotlessi ; B 95 0 505 426 ;
+C 248 ; WX 600 ; N lslash ; B 95 0 505 629 ;
+C 249 ; WX 600 ; N oslash ; B 62 -80 538 506 ;
+C 250 ; WX 600 ; N oe ; B 19 -15 559 441 ;
+C 251 ; WX 600 ; N germandbls ; B 48 -15 588 629 ;
+C -1 ; WX 600 ; N Odieresis ; B 43 -18 557 731 ;
+C -1 ; WX 600 ; N logicalnot ; B 87 108 513 369 ;
+C -1 ; WX 600 ; N minus ; B 80 232 520 283 ;
+C -1 ; WX 600 ; N merge ; B 160 -15 440 436 ;
+C -1 ; WX 600 ; N degree ; B 123 269 477 622 ;
+C -1 ; WX 600 ; N dectab ; B 18 0 582 227 ;
+C -1 ; WX 600 ; N ll ; B 18 0 567 629 ;
+C -1 ; WX 600 ; N IJ ; B 32 -18 583 562 ;
+C -1 ; WX 600 ; N Eacute ; B 53 0 550 793 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 43 -18 557 775 ;
+C -1 ; WX 600 ; N ucircumflex ; B 21 -15 562 654 ;
+C -1 ; WX 600 ; N left ; B 70 68 530 348 ;
+C -1 ; WX 600 ; N threesuperior ; B 155 240 406 622 ;
+C -1 ; WX 600 ; N up ; B 160 0 440 437 ;
+C -1 ; WX 600 ; N multiply ; B 87 43 515 470 ;
+C -1 ; WX 600 ; N Scaron ; B 72 -20 529 805 ;
+C -1 ; WX 600 ; N tab ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N Ucircumflex ; B 17 -18 583 775 ;
+C -1 ; WX 600 ; N divide ; B 87 48 513 467 ;
+C -1 ; WX 600 ; N Acircumflex ; B 3 0 597 775 ;
+C -1 ; WX 600 ; N eacute ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N uacute ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N Aacute ; B 3 0 597 793 ;
+C -1 ; WX 600 ; N copyright ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N twosuperior ; B 177 249 424 622 ;
+C -1 ; WX 600 ; N Ecircumflex ; B 53 0 550 775 ;
+C -1 ; WX 600 ; N ntilde ; B 26 0 575 606 ;
+C -1 ; WX 600 ; N down ; B 160 -15 440 426 ;
+C -1 ; WX 600 ; N center ; B 40 14 560 580 ;
+C -1 ; WX 600 ; N onesuperior ; B 172 249 428 622 ;
+C -1 ; WX 600 ; N ij ; B 37 -157 490 657 ;
+C -1 ; WX 600 ; N edieresis ; B 66 -15 548 595 ;
+C -1 ; WX 600 ; N graybox ; B 76 0 525 599 ;
+C -1 ; WX 600 ; N odieresis ; B 62 -15 538 595 ;
+C -1 ; WX 600 ; N Ograve ; B 43 -18 557 793 ;
+C -1 ; WX 600 ; N threequarters ; B 8 -56 593 666 ;
+C -1 ; WX 600 ; N plusminus ; B 87 44 513 558 ;
+C -1 ; WX 600 ; N prescription ; B 27 -15 577 562 ;
+C -1 ; WX 600 ; N eth ; B 62 -15 538 629 ;
+C -1 ; WX 600 ; N largebullet ; B 261 220 339 297 ;
+C -1 ; WX 600 ; N egrave ; B 66 -15 548 672 ;
+C -1 ; WX 600 ; N ccedilla ; B 66 -151 529 441 ;
+C -1 ; WX 600 ; N notegraphic ; B 136 -15 464 572 ;
+C -1 ; WX 600 ; N Udieresis ; B 17 -18 583 731 ;
+C -1 ; WX 600 ; N Gcaron ; B 31 -18 575 805 ;
+C -1 ; WX 600 ; N arrowdown ; B 116 -15 484 608 ;
+C -1 ; WX 600 ; N format ; B 5 -157 56 607 ;
+C -1 ; WX 600 ; N Otilde ; B 43 -18 557 732 ;
+C -1 ; WX 600 ; N Idieresis ; B 96 0 504 731 ;
+C -1 ; WX 600 ; N adieresis ; B 53 -15 559 595 ;
+C -1 ; WX 600 ; N ecircumflex ; B 66 -15 548 654 ;
+C -1 ; WX 600 ; N Eth ; B 30 0 574 562 ;
+C -1 ; WX 600 ; N onequarter ; B 0 -57 600 665 ;
+C -1 ; WX 600 ; N LL ; B 8 0 592 562 ;
+C -1 ; WX 600 ; N agrave ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N Zcaron ; B 86 0 514 805 ;
+C -1 ; WX 600 ; N Scedilla ; B 72 -151 529 580 ;
+C -1 ; WX 600 ; N Idot ; B 96 0 504 716 ;
+C -1 ; WX 600 ; N Iacute ; B 96 0 504 793 ;
+C -1 ; WX 600 ; N indent ; B 70 68 530 348 ;
+C -1 ; WX 600 ; N Ugrave ; B 17 -18 583 793 ;
+C -1 ; WX 600 ; N scaron ; B 80 -15 513 669 ;
+C -1 ; WX 600 ; N overscore ; B 0 579 600 629 ;
+C -1 ; WX 600 ; N Aring ; B 3 0 597 753 ;
+C -1 ; WX 600 ; N Ccedilla ; B 41 -151 540 580 ;
+C -1 ; WX 600 ; N Igrave ; B 96 0 504 793 ;
+C -1 ; WX 600 ; N brokenbar ; B 275 -175 326 675 ;
+C -1 ; WX 600 ; N Oacute ; B 43 -18 557 793 ;
+C -1 ; WX 600 ; N otilde ; B 62 -15 538 606 ;
+C -1 ; WX 600 ; N Yacute ; B 24 0 576 793 ;
+C -1 ; WX 600 ; N lira ; B 73 -21 521 611 ;
+C -1 ; WX 600 ; N Icircumflex ; B 96 0 504 775 ;
+C -1 ; WX 600 ; N Atilde ; B 3 0 597 732 ;
+C -1 ; WX 600 ; N Uacute ; B 17 -18 583 793 ;
+C -1 ; WX 600 ; N Ydieresis ; B 24 0 576 731 ;
+C -1 ; WX 600 ; N ydieresis ; B 7 -157 592 595 ;
+C -1 ; WX 600 ; N idieresis ; B 95 0 505 595 ;
+C -1 ; WX 600 ; N Adieresis ; B 3 0 597 731 ;
+C -1 ; WX 600 ; N mu ; B 21 -157 562 426 ;
+C -1 ; WX 600 ; N trademark ; B -23 263 623 562 ;
+C -1 ; WX 600 ; N oacute ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N acircumflex ; B 53 -15 559 654 ;
+C -1 ; WX 600 ; N Agrave ; B 3 0 597 793 ;
+C -1 ; WX 600 ; N return ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N atilde ; B 53 -15 559 606 ;
+C -1 ; WX 600 ; N square ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N registered ; B 0 -18 600 580 ;
+C -1 ; WX 600 ; N stop ; B 19 0 581 562 ;
+C -1 ; WX 600 ; N udieresis ; B 21 -15 562 595 ;
+C -1 ; WX 600 ; N arrowup ; B 116 0 484 623 ;
+C -1 ; WX 600 ; N igrave ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N Edieresis ; B 53 0 550 731 ;
+C -1 ; WX 600 ; N zcaron ; B 99 0 502 669 ;
+C -1 ; WX 600 ; N arrowboth ; B -28 115 628 483 ;
+C -1 ; WX 600 ; N gcaron ; B 45 -157 566 669 ;
+C -1 ; WX 600 ; N arrowleft ; B -24 115 624 483 ;
+C -1 ; WX 600 ; N aacute ; B 53 -15 559 672 ;
+C -1 ; WX 600 ; N ocircumflex ; B 62 -15 538 654 ;
+C -1 ; WX 600 ; N scedilla ; B 80 -151 513 441 ;
+C -1 ; WX 600 ; N ograve ; B 62 -15 538 672 ;
+C -1 ; WX 600 ; N onehalf ; B 0 -57 611 665 ;
+C -1 ; WX 600 ; N ugrave ; B 21 -15 562 672 ;
+C -1 ; WX 600 ; N Ntilde ; B 7 -13 593 732 ;
+C -1 ; WX 600 ; N iacute ; B 95 0 505 672 ;
+C -1 ; WX 600 ; N arrowright ; B -24 115 624 483 ;
+C -1 ; WX 600 ; N Thorn ; B 79 0 538 562 ;
+C -1 ; WX 600 ; N Egrave ; B 53 0 550 793 ;
+C -1 ; WX 600 ; N thorn ; B -6 -157 555 629 ;
+C -1 ; WX 600 ; N aring ; B 53 -15 559 627 ;
+C -1 ; WX 600 ; N yacute ; B 7 -157 592 672 ;
+C -1 ; WX 600 ; N icircumflex ; B 94 0 505 654 ;
+EndCharMetrics
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 20 121 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex -30 121 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis -30 136 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave -30 121 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring -15 126 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 0 126 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 30 121 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 0 121 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 0 136 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 0 121 ;
+CC Gcaron 2 ; PCC G 0 0 ; PCC caron 0 136 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 121 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 121 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 136 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 121 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 0 126 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 0 121 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 0 121 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 0 136 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 0 121 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 0 126 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 30 136 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 30 121 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 0 121 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 0 136 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave -30 121 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 30 121 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 0 136 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 0 136 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 0 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 0 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 0 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 0 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 0 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 0 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 0 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 0 0 ;
+CC gcaron 2 ; PCC g 0 0 ; PCC caron -30 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -30 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -30 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -30 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 0 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 0 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 0 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 0 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 0 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 0 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 0 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute -10 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex -10 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 0 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave -30 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute -20 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis -10 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 10 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Bold.afm b/tlt3.0/library/afm/Helvetica-Bold.afm
new file mode 100644
index 0000000..f428198
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Bold.afm
@@ -0,0 +1,571 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu Mar 15 09:43:00 1990
+Comment UniqueID 28357
+Comment VMusage 26878 33770
+FontName Helvetica-Bold
+FullName Helvetica Bold
+FamilyName Helvetica
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -170 -228 1003 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 90 0 244 718 ;
+C 34 ; WX 474 ; N quotedbl ; B 98 447 376 718 ;
+C 35 ; WX 556 ; N numbersign ; B 18 0 538 698 ;
+C 36 ; WX 556 ; N dollar ; B 30 -115 523 775 ;
+C 37 ; WX 889 ; N percent ; B 28 -19 861 710 ;
+C 38 ; WX 722 ; N ampersand ; B 54 -19 701 718 ;
+C 39 ; WX 278 ; N quoteright ; B 69 445 209 718 ;
+C 40 ; WX 333 ; N parenleft ; B 35 -208 314 734 ;
+C 41 ; WX 333 ; N parenright ; B 19 -208 298 734 ;
+C 42 ; WX 389 ; N asterisk ; B 27 387 362 718 ;
+C 43 ; WX 584 ; N plus ; B 40 0 544 506 ;
+C 44 ; WX 278 ; N comma ; B 64 -168 214 146 ;
+C 45 ; WX 333 ; N hyphen ; B 27 215 306 345 ;
+C 46 ; WX 278 ; N period ; B 64 0 214 146 ;
+C 47 ; WX 278 ; N slash ; B -33 -19 311 737 ;
+C 48 ; WX 556 ; N zero ; B 32 -19 524 710 ;
+C 49 ; WX 556 ; N one ; B 69 0 378 710 ;
+C 50 ; WX 556 ; N two ; B 26 0 511 710 ;
+C 51 ; WX 556 ; N three ; B 27 -19 516 710 ;
+C 52 ; WX 556 ; N four ; B 27 0 526 710 ;
+C 53 ; WX 556 ; N five ; B 27 -19 516 698 ;
+C 54 ; WX 556 ; N six ; B 31 -19 520 710 ;
+C 55 ; WX 556 ; N seven ; B 25 0 528 698 ;
+C 56 ; WX 556 ; N eight ; B 32 -19 524 710 ;
+C 57 ; WX 556 ; N nine ; B 30 -19 522 710 ;
+C 58 ; WX 333 ; N colon ; B 92 0 242 512 ;
+C 59 ; WX 333 ; N semicolon ; B 92 -168 242 512 ;
+C 60 ; WX 584 ; N less ; B 38 -8 546 514 ;
+C 61 ; WX 584 ; N equal ; B 40 87 544 419 ;
+C 62 ; WX 584 ; N greater ; B 38 -8 546 514 ;
+C 63 ; WX 611 ; N question ; B 60 0 556 727 ;
+C 64 ; WX 975 ; N at ; B 118 -19 856 737 ;
+C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
+C 66 ; WX 722 ; N B ; B 76 0 669 718 ;
+C 67 ; WX 722 ; N C ; B 44 -19 684 737 ;
+C 68 ; WX 722 ; N D ; B 76 0 685 718 ;
+C 69 ; WX 667 ; N E ; B 76 0 621 718 ;
+C 70 ; WX 611 ; N F ; B 76 0 587 718 ;
+C 71 ; WX 778 ; N G ; B 44 -19 713 737 ;
+C 72 ; WX 722 ; N H ; B 71 0 651 718 ;
+C 73 ; WX 278 ; N I ; B 64 0 214 718 ;
+C 74 ; WX 556 ; N J ; B 22 -18 484 718 ;
+C 75 ; WX 722 ; N K ; B 87 0 722 718 ;
+C 76 ; WX 611 ; N L ; B 76 0 583 718 ;
+C 77 ; WX 833 ; N M ; B 69 0 765 718 ;
+C 78 ; WX 722 ; N N ; B 69 0 654 718 ;
+C 79 ; WX 778 ; N O ; B 44 -19 734 737 ;
+C 80 ; WX 667 ; N P ; B 76 0 627 718 ;
+C 81 ; WX 778 ; N Q ; B 44 -52 737 737 ;
+C 82 ; WX 722 ; N R ; B 76 0 677 718 ;
+C 83 ; WX 667 ; N S ; B 39 -19 629 737 ;
+C 84 ; WX 611 ; N T ; B 14 0 598 718 ;
+C 85 ; WX 722 ; N U ; B 72 -19 651 718 ;
+C 86 ; WX 667 ; N V ; B 19 0 648 718 ;
+C 87 ; WX 944 ; N W ; B 16 0 929 718 ;
+C 88 ; WX 667 ; N X ; B 14 0 653 718 ;
+C 89 ; WX 667 ; N Y ; B 15 0 653 718 ;
+C 90 ; WX 611 ; N Z ; B 25 0 586 718 ;
+C 91 ; WX 333 ; N bracketleft ; B 63 -196 309 722 ;
+C 92 ; WX 278 ; N backslash ; B -33 -19 311 737 ;
+C 93 ; WX 333 ; N bracketright ; B 24 -196 270 722 ;
+C 94 ; WX 584 ; N asciicircum ; B 62 323 522 698 ;
+C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 69 454 209 727 ;
+C 97 ; WX 556 ; N a ; B 29 -14 527 546 ;
+C 98 ; WX 611 ; N b ; B 61 -14 578 718 ;
+C 99 ; WX 556 ; N c ; B 34 -14 524 546 ;
+C 100 ; WX 611 ; N d ; B 34 -14 551 718 ;
+C 101 ; WX 556 ; N e ; B 23 -14 528 546 ;
+C 102 ; WX 333 ; N f ; B 10 0 318 727 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B 40 -217 553 546 ;
+C 104 ; WX 611 ; N h ; B 65 0 546 718 ;
+C 105 ; WX 278 ; N i ; B 69 0 209 725 ;
+C 106 ; WX 278 ; N j ; B 3 -214 209 725 ;
+C 107 ; WX 556 ; N k ; B 69 0 562 718 ;
+C 108 ; WX 278 ; N l ; B 69 0 209 718 ;
+C 109 ; WX 889 ; N m ; B 64 0 826 546 ;
+C 110 ; WX 611 ; N n ; B 65 0 546 546 ;
+C 111 ; WX 611 ; N o ; B 34 -14 578 546 ;
+C 112 ; WX 611 ; N p ; B 62 -207 578 546 ;
+C 113 ; WX 611 ; N q ; B 34 -207 552 546 ;
+C 114 ; WX 389 ; N r ; B 64 0 373 546 ;
+C 115 ; WX 556 ; N s ; B 30 -14 519 546 ;
+C 116 ; WX 333 ; N t ; B 10 -6 309 676 ;
+C 117 ; WX 611 ; N u ; B 66 -14 545 532 ;
+C 118 ; WX 556 ; N v ; B 13 0 543 532 ;
+C 119 ; WX 778 ; N w ; B 10 0 769 532 ;
+C 120 ; WX 556 ; N x ; B 15 0 541 532 ;
+C 121 ; WX 556 ; N y ; B 10 -214 539 532 ;
+C 122 ; WX 500 ; N z ; B 20 0 480 532 ;
+C 123 ; WX 389 ; N braceleft ; B 48 -196 365 722 ;
+C 124 ; WX 280 ; N bar ; B 84 -19 196 737 ;
+C 125 ; WX 389 ; N braceright ; B 24 -196 341 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 61 163 523 343 ;
+C 161 ; WX 333 ; N exclamdown ; B 90 -186 244 532 ;
+C 162 ; WX 556 ; N cent ; B 34 -118 524 628 ;
+C 163 ; WX 556 ; N sterling ; B 28 -16 541 718 ;
+C 164 ; WX 167 ; N fraction ; B -170 -19 336 710 ;
+C 165 ; WX 556 ; N yen ; B -9 0 565 698 ;
+C 166 ; WX 556 ; N florin ; B -10 -210 516 737 ;
+C 167 ; WX 556 ; N section ; B 34 -184 522 727 ;
+C 168 ; WX 556 ; N currency ; B -3 76 559 636 ;
+C 169 ; WX 238 ; N quotesingle ; B 70 447 168 718 ;
+C 170 ; WX 500 ; N quotedblleft ; B 64 454 436 727 ;
+C 171 ; WX 556 ; N guillemotleft ; B 88 76 468 484 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 83 76 250 484 ;
+C 173 ; WX 333 ; N guilsinglright ; B 83 76 250 484 ;
+C 174 ; WX 611 ; N fi ; B 10 0 542 727 ;
+C 175 ; WX 611 ; N fl ; B 10 0 542 727 ;
+C 177 ; WX 556 ; N endash ; B 0 227 556 333 ;
+C 178 ; WX 556 ; N dagger ; B 36 -171 520 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 36 -171 520 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 58 172 220 334 ;
+C 182 ; WX 556 ; N paragraph ; B -8 -191 539 700 ;
+C 183 ; WX 350 ; N bullet ; B 10 194 340 524 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 69 -146 209 127 ;
+C 185 ; WX 500 ; N quotedblbase ; B 64 -146 436 127 ;
+C 186 ; WX 500 ; N quotedblright ; B 64 445 436 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 88 76 468 484 ;
+C 188 ; WX 1000 ; N ellipsis ; B 92 0 908 146 ;
+C 189 ; WX 1000 ; N perthousand ; B -3 -19 1003 710 ;
+C 191 ; WX 611 ; N questiondown ; B 55 -195 551 532 ;
+C 193 ; WX 333 ; N grave ; B -23 604 225 750 ;
+C 194 ; WX 333 ; N acute ; B 108 604 356 750 ;
+C 195 ; WX 333 ; N circumflex ; B -10 604 343 750 ;
+C 196 ; WX 333 ; N tilde ; B -17 610 350 737 ;
+C 197 ; WX 333 ; N macron ; B -6 604 339 678 ;
+C 198 ; WX 333 ; N breve ; B -2 604 335 750 ;
+C 199 ; WX 333 ; N dotaccent ; B 104 614 230 729 ;
+C 200 ; WX 333 ; N dieresis ; B 6 614 327 729 ;
+C 202 ; WX 333 ; N ring ; B 59 568 275 776 ;
+C 203 ; WX 333 ; N cedilla ; B 6 -228 245 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 9 604 486 750 ;
+C 206 ; WX 333 ; N ogonek ; B 71 -228 304 0 ;
+C 207 ; WX 333 ; N caron ; B -10 604 343 750 ;
+C 208 ; WX 1000 ; N emdash ; B 0 227 1000 333 ;
+C 225 ; WX 1000 ; N AE ; B 5 0 954 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 22 276 347 737 ;
+C 232 ; WX 611 ; N Lslash ; B -20 0 583 718 ;
+C 233 ; WX 778 ; N Oslash ; B 33 -27 744 745 ;
+C 234 ; WX 1000 ; N OE ; B 37 -19 961 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 6 276 360 737 ;
+C 241 ; WX 889 ; N ae ; B 29 -14 858 546 ;
+C 245 ; WX 278 ; N dotlessi ; B 69 0 209 532 ;
+C 248 ; WX 278 ; N lslash ; B -18 0 296 718 ;
+C 249 ; WX 611 ; N oslash ; B 22 -29 589 560 ;
+C 250 ; WX 944 ; N oe ; B 34 -14 912 546 ;
+C 251 ; WX 611 ; N germandbls ; B 69 -14 579 731 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 586 936 ;
+C -1 ; WX 556 ; N ccedilla ; B 34 -228 524 546 ;
+C -1 ; WX 556 ; N ydieresis ; B 10 -214 539 729 ;
+C -1 ; WX 556 ; N atilde ; B 29 -14 527 737 ;
+C -1 ; WX 278 ; N icircumflex ; B -37 0 316 750 ;
+C -1 ; WX 333 ; N threesuperior ; B 8 271 326 710 ;
+C -1 ; WX 556 ; N ecircumflex ; B 23 -14 528 750 ;
+C -1 ; WX 611 ; N thorn ; B 62 -208 578 718 ;
+C -1 ; WX 556 ; N egrave ; B 23 -14 528 750 ;
+C -1 ; WX 333 ; N twosuperior ; B 9 283 324 710 ;
+C -1 ; WX 556 ; N eacute ; B 23 -14 528 750 ;
+C -1 ; WX 611 ; N otilde ; B 34 -14 578 737 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 702 936 ;
+C -1 ; WX 611 ; N ocircumflex ; B 34 -14 578 750 ;
+C -1 ; WX 556 ; N yacute ; B 10 -214 539 750 ;
+C -1 ; WX 611 ; N udieresis ; B 66 -14 545 729 ;
+C -1 ; WX 834 ; N threequarters ; B 16 -19 799 710 ;
+C -1 ; WX 556 ; N acircumflex ; B 29 -14 527 750 ;
+C -1 ; WX 722 ; N Eth ; B -5 0 685 718 ;
+C -1 ; WX 556 ; N edieresis ; B 23 -14 528 729 ;
+C -1 ; WX 611 ; N ugrave ; B 66 -14 545 750 ;
+C -1 ; WX 1000 ; N trademark ; B 44 306 956 718 ;
+C -1 ; WX 611 ; N ograve ; B 34 -14 578 750 ;
+C -1 ; WX 556 ; N scaron ; B 30 -14 519 750 ;
+C -1 ; WX 278 ; N Idieresis ; B -21 0 300 915 ;
+C -1 ; WX 611 ; N uacute ; B 66 -14 545 750 ;
+C -1 ; WX 556 ; N agrave ; B 29 -14 527 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 546 737 ;
+C -1 ; WX 556 ; N aring ; B 29 -14 527 776 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 480 750 ;
+C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 936 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 654 923 ;
+C -1 ; WX 611 ; N ucircumflex ; B 66 -14 545 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 621 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 329 936 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -228 684 737 ;
+C -1 ; WX 778 ; N Odieresis ; B 44 -19 734 915 ;
+C -1 ; WX 667 ; N Scaron ; B 39 -19 629 936 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 621 915 ;
+C -1 ; WX 278 ; N Igrave ; B -50 0 214 936 ;
+C -1 ; WX 556 ; N adieresis ; B 29 -14 527 729 ;
+C -1 ; WX 778 ; N Ograve ; B 44 -19 734 936 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 621 936 ;
+C -1 ; WX 667 ; N Ydieresis ; B 15 0 653 915 ;
+C -1 ; WX 737 ; N registered ; B -11 -19 748 737 ;
+C -1 ; WX 778 ; N Otilde ; B 44 -19 734 923 ;
+C -1 ; WX 834 ; N onequarter ; B 26 -19 766 710 ;
+C -1 ; WX 722 ; N Ugrave ; B 72 -19 651 936 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 72 -19 651 936 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 627 718 ;
+C -1 ; WX 584 ; N divide ; B 40 -42 544 548 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 702 923 ;
+C -1 ; WX 722 ; N Uacute ; B 72 -19 651 936 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 44 -19 734 936 ;
+C -1 ; WX 584 ; N logicalnot ; B 40 108 544 419 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 278 ; N idieresis ; B -21 0 300 729 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 329 750 ;
+C -1 ; WX 556 ; N aacute ; B 29 -14 527 750 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 544 506 ;
+C -1 ; WX 584 ; N multiply ; B 40 1 545 505 ;
+C -1 ; WX 722 ; N Udieresis ; B 72 -19 651 915 ;
+C -1 ; WX 584 ; N minus ; B 40 197 544 309 ;
+C -1 ; WX 333 ; N onesuperior ; B 26 283 237 710 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 621 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 702 936 ;
+C -1 ; WX 737 ; N copyright ; B -11 -19 749 737 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 611 ; N odieresis ; B 34 -14 578 729 ;
+C -1 ; WX 611 ; N oacute ; B 34 -14 578 750 ;
+C -1 ; WX 400 ; N degree ; B 57 426 343 712 ;
+C -1 ; WX 278 ; N igrave ; B -50 0 209 750 ;
+C -1 ; WX 611 ; N mu ; B 66 -207 545 532 ;
+C -1 ; WX 778 ; N Oacute ; B 44 -19 734 936 ;
+C -1 ; WX 611 ; N eth ; B 34 -14 578 737 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 702 915 ;
+C -1 ; WX 667 ; N Yacute ; B 15 0 653 936 ;
+C -1 ; WX 280 ; N brokenbar ; B 84 -19 196 737 ;
+C -1 ; WX 834 ; N onehalf ; B 26 -19 794 710 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 209
+
+KPX A y -30
+KPX A w -30
+KPX A v -40
+KPX A u -30
+KPX A Y -110
+KPX A W -60
+KPX A V -80
+KPX A U -50
+KPX A T -90
+KPX A Q -40
+KPX A O -40
+KPX A G -50
+KPX A C -40
+
+KPX B U -10
+KPX B A -30
+
+KPX D period -30
+KPX D comma -30
+KPX D Y -70
+KPX D W -40
+KPX D V -40
+KPX D A -40
+
+KPX F period -100
+KPX F comma -100
+KPX F a -20
+KPX F A -80
+
+KPX J u -20
+KPX J period -20
+KPX J comma -20
+KPX J A -20
+
+KPX K y -40
+KPX K u -30
+KPX K o -35
+KPX K e -15
+KPX K O -30
+
+KPX L y -30
+KPX L quoteright -140
+KPX L quotedblright -140
+KPX L Y -120
+KPX L W -80
+KPX L V -110
+KPX L T -90
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -50
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -50
+
+KPX P period -120
+KPX P o -40
+KPX P e -30
+KPX P comma -120
+KPX P a -30
+KPX P A -100
+
+KPX Q period 20
+KPX Q comma 20
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -40
+KPX R V -50
+KPX R U -20
+KPX R T -20
+KPX R O -20
+
+KPX T y -60
+KPX T w -60
+KPX T u -90
+KPX T semicolon -40
+KPX T r -80
+KPX T period -80
+KPX T o -80
+KPX T hyphen -120
+KPX T e -60
+KPX T comma -80
+KPX T colon -40
+KPX T a -80
+KPX T O -40
+KPX T A -90
+
+KPX U period -30
+KPX U comma -30
+KPX U A -50
+
+KPX V u -60
+KPX V semicolon -40
+KPX V period -120
+KPX V o -90
+KPX V hyphen -80
+KPX V e -50
+KPX V comma -120
+KPX V colon -40
+KPX V a -60
+KPX V O -50
+KPX V G -50
+KPX V A -80
+
+KPX W y -20
+KPX W u -45
+KPX W semicolon -10
+KPX W period -80
+KPX W o -60
+KPX W hyphen -40
+KPX W e -35
+KPX W comma -80
+KPX W colon -10
+KPX W a -40
+KPX W O -20
+KPX W A -60
+
+KPX Y u -100
+KPX Y semicolon -50
+KPX Y period -100
+KPX Y o -100
+KPX Y e -80
+KPX Y comma -100
+KPX Y colon -50
+KPX Y a -90
+KPX Y O -70
+KPX Y A -110
+
+KPX a y -20
+KPX a w -15
+KPX a v -15
+KPX a g -10
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b l -10
+
+KPX c y -10
+KPX c l -20
+KPX c k -20
+KPX c h -10
+
+KPX colon space -40
+
+KPX comma space -40
+KPX comma quoteright -120
+KPX comma quotedblright -120
+
+KPX d y -15
+KPX d w -15
+KPX d v -15
+KPX d d -10
+
+KPX e y -15
+KPX e x -15
+KPX e w -15
+KPX e v -15
+KPX e period 20
+KPX e comma 10
+
+KPX f quoteright 30
+KPX f quotedblright 30
+KPX f period -10
+KPX f o -20
+KPX f e -10
+KPX f comma -10
+
+KPX g g -10
+KPX g e 10
+
+KPX h y -20
+
+KPX k o -15
+
+KPX l y -15
+KPX l w -15
+
+KPX m y -30
+KPX m u -20
+
+KPX n y -20
+KPX n v -40
+KPX n u -10
+
+KPX o y -20
+KPX o x -30
+KPX o w -15
+KPX o v -20
+
+KPX p y -15
+
+KPX period space -40
+KPX period quoteright -120
+KPX period quotedblright -120
+
+KPX quotedblright space -80
+
+KPX quoteleft quoteleft -46
+
+KPX quoteright v -20
+KPX quoteright space -80
+KPX quoteright s -60
+KPX quoteright r -40
+KPX quoteright quoteright -46
+KPX quoteright l -20
+KPX quoteright d -80
+
+KPX r y 10
+KPX r v 10
+KPX r t 20
+KPX r s -15
+KPX r q -20
+KPX r period -60
+KPX r o -20
+KPX r hyphen -20
+KPX r g -15
+KPX r d -20
+KPX r comma -60
+KPX r c -20
+
+KPX s w -15
+
+KPX semicolon space -40
+
+KPX space quoteleft -60
+KPX space quotedblleft -80
+KPX space Y -120
+KPX space W -80
+KPX space V -80
+KPX space T -100
+
+KPX v period -80
+KPX v o -30
+KPX v comma -80
+KPX v a -20
+
+KPX w period -40
+KPX w o -20
+KPX w comma -40
+
+KPX x e -10
+
+KPX y period -80
+KPX y o -25
+KPX y e -10
+KPX y comma -80
+KPX y a -30
+
+KPX z e 10
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 186 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 195 186 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 186 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 215 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 167 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 167 186 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 167 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 167 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 186 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 186 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 186 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 186 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 167 186 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 186 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 167 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 167 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 186 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 132 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 139 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 139 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 139 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 139 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 112 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 112 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-BoldOblique.afm b/tlt3.0/library/afm/Helvetica-BoldOblique.afm
new file mode 100644
index 0000000..0df5aaf
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-BoldOblique.afm
@@ -0,0 +1,571 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu Mar 15 10:44:33 1990
+Comment UniqueID 28371
+Comment VMusage 7614 43068
+FontName Helvetica-BoldOblique
+FullName Helvetica Bold Oblique
+FamilyName Helvetica
+Weight Bold
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -174 -228 1114 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 94 0 397 718 ;
+C 34 ; WX 474 ; N quotedbl ; B 193 447 529 718 ;
+C 35 ; WX 556 ; N numbersign ; B 60 0 644 698 ;
+C 36 ; WX 556 ; N dollar ; B 67 -115 622 775 ;
+C 37 ; WX 889 ; N percent ; B 136 -19 901 710 ;
+C 38 ; WX 722 ; N ampersand ; B 89 -19 732 718 ;
+C 39 ; WX 278 ; N quoteright ; B 167 445 362 718 ;
+C 40 ; WX 333 ; N parenleft ; B 76 -208 470 734 ;
+C 41 ; WX 333 ; N parenright ; B -25 -208 369 734 ;
+C 42 ; WX 389 ; N asterisk ; B 146 387 481 718 ;
+C 43 ; WX 584 ; N plus ; B 82 0 610 506 ;
+C 44 ; WX 278 ; N comma ; B 28 -168 245 146 ;
+C 45 ; WX 333 ; N hyphen ; B 73 215 379 345 ;
+C 46 ; WX 278 ; N period ; B 64 0 245 146 ;
+C 47 ; WX 278 ; N slash ; B -37 -19 468 737 ;
+C 48 ; WX 556 ; N zero ; B 86 -19 617 710 ;
+C 49 ; WX 556 ; N one ; B 173 0 529 710 ;
+C 50 ; WX 556 ; N two ; B 26 0 619 710 ;
+C 51 ; WX 556 ; N three ; B 65 -19 608 710 ;
+C 52 ; WX 556 ; N four ; B 60 0 598 710 ;
+C 53 ; WX 556 ; N five ; B 64 -19 636 698 ;
+C 54 ; WX 556 ; N six ; B 85 -19 619 710 ;
+C 55 ; WX 556 ; N seven ; B 125 0 676 698 ;
+C 56 ; WX 556 ; N eight ; B 69 -19 616 710 ;
+C 57 ; WX 556 ; N nine ; B 78 -19 615 710 ;
+C 58 ; WX 333 ; N colon ; B 92 0 351 512 ;
+C 59 ; WX 333 ; N semicolon ; B 56 -168 351 512 ;
+C 60 ; WX 584 ; N less ; B 82 -8 655 514 ;
+C 61 ; WX 584 ; N equal ; B 58 87 633 419 ;
+C 62 ; WX 584 ; N greater ; B 36 -8 609 514 ;
+C 63 ; WX 611 ; N question ; B 165 0 671 727 ;
+C 64 ; WX 975 ; N at ; B 186 -19 954 737 ;
+C 65 ; WX 722 ; N A ; B 20 0 702 718 ;
+C 66 ; WX 722 ; N B ; B 76 0 764 718 ;
+C 67 ; WX 722 ; N C ; B 107 -19 789 737 ;
+C 68 ; WX 722 ; N D ; B 76 0 777 718 ;
+C 69 ; WX 667 ; N E ; B 76 0 757 718 ;
+C 70 ; WX 611 ; N F ; B 76 0 740 718 ;
+C 71 ; WX 778 ; N G ; B 108 -19 817 737 ;
+C 72 ; WX 722 ; N H ; B 71 0 804 718 ;
+C 73 ; WX 278 ; N I ; B 64 0 367 718 ;
+C 74 ; WX 556 ; N J ; B 60 -18 637 718 ;
+C 75 ; WX 722 ; N K ; B 87 0 858 718 ;
+C 76 ; WX 611 ; N L ; B 76 0 611 718 ;
+C 77 ; WX 833 ; N M ; B 69 0 918 718 ;
+C 78 ; WX 722 ; N N ; B 69 0 807 718 ;
+C 79 ; WX 778 ; N O ; B 107 -19 823 737 ;
+C 80 ; WX 667 ; N P ; B 76 0 738 718 ;
+C 81 ; WX 778 ; N Q ; B 107 -52 823 737 ;
+C 82 ; WX 722 ; N R ; B 76 0 778 718 ;
+C 83 ; WX 667 ; N S ; B 81 -19 718 737 ;
+C 84 ; WX 611 ; N T ; B 140 0 751 718 ;
+C 85 ; WX 722 ; N U ; B 116 -19 804 718 ;
+C 86 ; WX 667 ; N V ; B 172 0 801 718 ;
+C 87 ; WX 944 ; N W ; B 169 0 1082 718 ;
+C 88 ; WX 667 ; N X ; B 14 0 791 718 ;
+C 89 ; WX 667 ; N Y ; B 168 0 806 718 ;
+C 90 ; WX 611 ; N Z ; B 25 0 737 718 ;
+C 91 ; WX 333 ; N bracketleft ; B 21 -196 462 722 ;
+C 92 ; WX 278 ; N backslash ; B 124 -19 307 737 ;
+C 93 ; WX 333 ; N bracketright ; B -18 -196 423 722 ;
+C 94 ; WX 584 ; N asciicircum ; B 131 323 591 698 ;
+C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 165 454 361 727 ;
+C 97 ; WX 556 ; N a ; B 55 -14 583 546 ;
+C 98 ; WX 611 ; N b ; B 61 -14 645 718 ;
+C 99 ; WX 556 ; N c ; B 79 -14 599 546 ;
+C 100 ; WX 611 ; N d ; B 82 -14 704 718 ;
+C 101 ; WX 556 ; N e ; B 70 -14 593 546 ;
+C 102 ; WX 333 ; N f ; B 87 0 469 727 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B 38 -217 666 546 ;
+C 104 ; WX 611 ; N h ; B 65 0 629 718 ;
+C 105 ; WX 278 ; N i ; B 69 0 363 725 ;
+C 106 ; WX 278 ; N j ; B -42 -214 363 725 ;
+C 107 ; WX 556 ; N k ; B 69 0 670 718 ;
+C 108 ; WX 278 ; N l ; B 69 0 362 718 ;
+C 109 ; WX 889 ; N m ; B 64 0 909 546 ;
+C 110 ; WX 611 ; N n ; B 65 0 629 546 ;
+C 111 ; WX 611 ; N o ; B 82 -14 643 546 ;
+C 112 ; WX 611 ; N p ; B 18 -207 645 546 ;
+C 113 ; WX 611 ; N q ; B 80 -207 665 546 ;
+C 114 ; WX 389 ; N r ; B 64 0 489 546 ;
+C 115 ; WX 556 ; N s ; B 63 -14 584 546 ;
+C 116 ; WX 333 ; N t ; B 100 -6 422 676 ;
+C 117 ; WX 611 ; N u ; B 98 -14 658 532 ;
+C 118 ; WX 556 ; N v ; B 126 0 656 532 ;
+C 119 ; WX 778 ; N w ; B 123 0 882 532 ;
+C 120 ; WX 556 ; N x ; B 15 0 648 532 ;
+C 121 ; WX 556 ; N y ; B 42 -214 652 532 ;
+C 122 ; WX 500 ; N z ; B 20 0 583 532 ;
+C 123 ; WX 389 ; N braceleft ; B 94 -196 518 722 ;
+C 124 ; WX 280 ; N bar ; B 80 -19 353 737 ;
+C 125 ; WX 389 ; N braceright ; B -18 -196 407 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 115 163 577 343 ;
+C 161 ; WX 333 ; N exclamdown ; B 50 -186 353 532 ;
+C 162 ; WX 556 ; N cent ; B 79 -118 599 628 ;
+C 163 ; WX 556 ; N sterling ; B 50 -16 635 718 ;
+C 164 ; WX 167 ; N fraction ; B -174 -19 487 710 ;
+C 165 ; WX 556 ; N yen ; B 60 0 713 698 ;
+C 166 ; WX 556 ; N florin ; B -50 -210 669 737 ;
+C 167 ; WX 556 ; N section ; B 61 -184 598 727 ;
+C 168 ; WX 556 ; N currency ; B 27 76 680 636 ;
+C 169 ; WX 238 ; N quotesingle ; B 165 447 321 718 ;
+C 170 ; WX 500 ; N quotedblleft ; B 160 454 588 727 ;
+C 171 ; WX 556 ; N guillemotleft ; B 135 76 571 484 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 130 76 353 484 ;
+C 173 ; WX 333 ; N guilsinglright ; B 99 76 322 484 ;
+C 174 ; WX 611 ; N fi ; B 87 0 696 727 ;
+C 175 ; WX 611 ; N fl ; B 87 0 695 727 ;
+C 177 ; WX 556 ; N endash ; B 48 227 627 333 ;
+C 178 ; WX 556 ; N dagger ; B 118 -171 626 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 46 -171 628 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 110 172 276 334 ;
+C 182 ; WX 556 ; N paragraph ; B 98 -191 688 700 ;
+C 183 ; WX 350 ; N bullet ; B 83 194 420 524 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 41 -146 236 127 ;
+C 185 ; WX 500 ; N quotedblbase ; B 36 -146 463 127 ;
+C 186 ; WX 500 ; N quotedblright ; B 162 445 589 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 104 76 540 484 ;
+C 188 ; WX 1000 ; N ellipsis ; B 92 0 939 146 ;
+C 189 ; WX 1000 ; N perthousand ; B 76 -19 1038 710 ;
+C 191 ; WX 611 ; N questiondown ; B 53 -195 559 532 ;
+C 193 ; WX 333 ; N grave ; B 136 604 353 750 ;
+C 194 ; WX 333 ; N acute ; B 236 604 515 750 ;
+C 195 ; WX 333 ; N circumflex ; B 118 604 471 750 ;
+C 196 ; WX 333 ; N tilde ; B 113 610 507 737 ;
+C 197 ; WX 333 ; N macron ; B 122 604 483 678 ;
+C 198 ; WX 333 ; N breve ; B 156 604 494 750 ;
+C 199 ; WX 333 ; N dotaccent ; B 235 614 385 729 ;
+C 200 ; WX 333 ; N dieresis ; B 137 614 482 729 ;
+C 202 ; WX 333 ; N ring ; B 200 568 420 776 ;
+C 203 ; WX 333 ; N cedilla ; B -37 -228 220 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 137 604 645 750 ;
+C 206 ; WX 333 ; N ogonek ; B 41 -228 264 0 ;
+C 207 ; WX 333 ; N caron ; B 149 604 502 750 ;
+C 208 ; WX 1000 ; N emdash ; B 48 227 1071 333 ;
+C 225 ; WX 1000 ; N AE ; B 5 0 1100 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 92 276 465 737 ;
+C 232 ; WX 611 ; N Lslash ; B 34 0 611 718 ;
+C 233 ; WX 778 ; N Oslash ; B 35 -27 894 745 ;
+C 234 ; WX 1000 ; N OE ; B 99 -19 1114 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 92 276 485 737 ;
+C 241 ; WX 889 ; N ae ; B 56 -14 923 546 ;
+C 245 ; WX 278 ; N dotlessi ; B 69 0 322 532 ;
+C 248 ; WX 278 ; N lslash ; B 40 0 407 718 ;
+C 249 ; WX 611 ; N oslash ; B 22 -29 701 560 ;
+C 250 ; WX 944 ; N oe ; B 82 -14 977 546 ;
+C 251 ; WX 611 ; N germandbls ; B 69 -14 657 731 ;
+C -1 ; WX 611 ; N Zcaron ; B 25 0 737 936 ;
+C -1 ; WX 556 ; N ccedilla ; B 79 -228 599 546 ;
+C -1 ; WX 556 ; N ydieresis ; B 42 -214 652 729 ;
+C -1 ; WX 556 ; N atilde ; B 55 -14 619 737 ;
+C -1 ; WX 278 ; N icircumflex ; B 69 0 444 750 ;
+C -1 ; WX 333 ; N threesuperior ; B 91 271 441 710 ;
+C -1 ; WX 556 ; N ecircumflex ; B 70 -14 593 750 ;
+C -1 ; WX 611 ; N thorn ; B 18 -208 645 718 ;
+C -1 ; WX 556 ; N egrave ; B 70 -14 593 750 ;
+C -1 ; WX 333 ; N twosuperior ; B 69 283 449 710 ;
+C -1 ; WX 556 ; N eacute ; B 70 -14 627 750 ;
+C -1 ; WX 611 ; N otilde ; B 82 -14 646 737 ;
+C -1 ; WX 722 ; N Aacute ; B 20 0 750 936 ;
+C -1 ; WX 611 ; N ocircumflex ; B 82 -14 643 750 ;
+C -1 ; WX 556 ; N yacute ; B 42 -214 652 750 ;
+C -1 ; WX 611 ; N udieresis ; B 98 -14 658 729 ;
+C -1 ; WX 834 ; N threequarters ; B 99 -19 839 710 ;
+C -1 ; WX 556 ; N acircumflex ; B 55 -14 583 750 ;
+C -1 ; WX 722 ; N Eth ; B 62 0 777 718 ;
+C -1 ; WX 556 ; N edieresis ; B 70 -14 594 729 ;
+C -1 ; WX 611 ; N ugrave ; B 98 -14 658 750 ;
+C -1 ; WX 1000 ; N trademark ; B 179 306 1109 718 ;
+C -1 ; WX 611 ; N ograve ; B 82 -14 643 750 ;
+C -1 ; WX 556 ; N scaron ; B 63 -14 614 750 ;
+C -1 ; WX 278 ; N Idieresis ; B 64 0 494 915 ;
+C -1 ; WX 611 ; N uacute ; B 98 -14 658 750 ;
+C -1 ; WX 556 ; N agrave ; B 55 -14 583 750 ;
+C -1 ; WX 611 ; N ntilde ; B 65 0 646 737 ;
+C -1 ; WX 556 ; N aring ; B 55 -14 583 776 ;
+C -1 ; WX 500 ; N zcaron ; B 20 0 586 750 ;
+C -1 ; WX 278 ; N Icircumflex ; B 64 0 484 936 ;
+C -1 ; WX 722 ; N Ntilde ; B 69 0 807 923 ;
+C -1 ; WX 611 ; N ucircumflex ; B 98 -14 658 750 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 76 0 757 936 ;
+C -1 ; WX 278 ; N Iacute ; B 64 0 528 936 ;
+C -1 ; WX 722 ; N Ccedilla ; B 107 -228 789 737 ;
+C -1 ; WX 778 ; N Odieresis ; B 107 -19 823 915 ;
+C -1 ; WX 667 ; N Scaron ; B 81 -19 718 936 ;
+C -1 ; WX 667 ; N Edieresis ; B 76 0 757 915 ;
+C -1 ; WX 278 ; N Igrave ; B 64 0 367 936 ;
+C -1 ; WX 556 ; N adieresis ; B 55 -14 594 729 ;
+C -1 ; WX 778 ; N Ograve ; B 107 -19 823 936 ;
+C -1 ; WX 667 ; N Egrave ; B 76 0 757 936 ;
+C -1 ; WX 667 ; N Ydieresis ; B 168 0 806 915 ;
+C -1 ; WX 737 ; N registered ; B 55 -19 834 737 ;
+C -1 ; WX 778 ; N Otilde ; B 107 -19 823 923 ;
+C -1 ; WX 834 ; N onequarter ; B 132 -19 806 710 ;
+C -1 ; WX 722 ; N Ugrave ; B 116 -19 804 936 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 116 -19 804 936 ;
+C -1 ; WX 667 ; N Thorn ; B 76 0 716 718 ;
+C -1 ; WX 584 ; N divide ; B 82 -42 610 548 ;
+C -1 ; WX 722 ; N Atilde ; B 20 0 741 923 ;
+C -1 ; WX 722 ; N Uacute ; B 116 -19 804 936 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 107 -19 823 936 ;
+C -1 ; WX 584 ; N logicalnot ; B 105 108 633 419 ;
+C -1 ; WX 722 ; N Aring ; B 20 0 702 962 ;
+C -1 ; WX 278 ; N idieresis ; B 69 0 455 729 ;
+C -1 ; WX 278 ; N iacute ; B 69 0 488 750 ;
+C -1 ; WX 556 ; N aacute ; B 55 -14 627 750 ;
+C -1 ; WX 584 ; N plusminus ; B 40 0 625 506 ;
+C -1 ; WX 584 ; N multiply ; B 57 1 635 505 ;
+C -1 ; WX 722 ; N Udieresis ; B 116 -19 804 915 ;
+C -1 ; WX 584 ; N minus ; B 82 197 610 309 ;
+C -1 ; WX 333 ; N onesuperior ; B 148 283 388 710 ;
+C -1 ; WX 667 ; N Eacute ; B 76 0 757 936 ;
+C -1 ; WX 722 ; N Acircumflex ; B 20 0 706 936 ;
+C -1 ; WX 737 ; N copyright ; B 56 -19 835 737 ;
+C -1 ; WX 722 ; N Agrave ; B 20 0 702 936 ;
+C -1 ; WX 611 ; N odieresis ; B 82 -14 643 729 ;
+C -1 ; WX 611 ; N oacute ; B 82 -14 654 750 ;
+C -1 ; WX 400 ; N degree ; B 175 426 467 712 ;
+C -1 ; WX 278 ; N igrave ; B 69 0 326 750 ;
+C -1 ; WX 611 ; N mu ; B 22 -207 658 532 ;
+C -1 ; WX 778 ; N Oacute ; B 107 -19 823 936 ;
+C -1 ; WX 611 ; N eth ; B 82 -14 670 737 ;
+C -1 ; WX 722 ; N Adieresis ; B 20 0 716 915 ;
+C -1 ; WX 667 ; N Yacute ; B 168 0 806 936 ;
+C -1 ; WX 280 ; N brokenbar ; B 80 -19 353 737 ;
+C -1 ; WX 834 ; N onehalf ; B 132 -19 858 710 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 209
+
+KPX A y -30
+KPX A w -30
+KPX A v -40
+KPX A u -30
+KPX A Y -110
+KPX A W -60
+KPX A V -80
+KPX A U -50
+KPX A T -90
+KPX A Q -40
+KPX A O -40
+KPX A G -50
+KPX A C -40
+
+KPX B U -10
+KPX B A -30
+
+KPX D period -30
+KPX D comma -30
+KPX D Y -70
+KPX D W -40
+KPX D V -40
+KPX D A -40
+
+KPX F period -100
+KPX F comma -100
+KPX F a -20
+KPX F A -80
+
+KPX J u -20
+KPX J period -20
+KPX J comma -20
+KPX J A -20
+
+KPX K y -40
+KPX K u -30
+KPX K o -35
+KPX K e -15
+KPX K O -30
+
+KPX L y -30
+KPX L quoteright -140
+KPX L quotedblright -140
+KPX L Y -120
+KPX L W -80
+KPX L V -110
+KPX L T -90
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -50
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -50
+
+KPX P period -120
+KPX P o -40
+KPX P e -30
+KPX P comma -120
+KPX P a -30
+KPX P A -100
+
+KPX Q period 20
+KPX Q comma 20
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -40
+KPX R V -50
+KPX R U -20
+KPX R T -20
+KPX R O -20
+
+KPX T y -60
+KPX T w -60
+KPX T u -90
+KPX T semicolon -40
+KPX T r -80
+KPX T period -80
+KPX T o -80
+KPX T hyphen -120
+KPX T e -60
+KPX T comma -80
+KPX T colon -40
+KPX T a -80
+KPX T O -40
+KPX T A -90
+
+KPX U period -30
+KPX U comma -30
+KPX U A -50
+
+KPX V u -60
+KPX V semicolon -40
+KPX V period -120
+KPX V o -90
+KPX V hyphen -80
+KPX V e -50
+KPX V comma -120
+KPX V colon -40
+KPX V a -60
+KPX V O -50
+KPX V G -50
+KPX V A -80
+
+KPX W y -20
+KPX W u -45
+KPX W semicolon -10
+KPX W period -80
+KPX W o -60
+KPX W hyphen -40
+KPX W e -35
+KPX W comma -80
+KPX W colon -10
+KPX W a -40
+KPX W O -20
+KPX W A -60
+
+KPX Y u -100
+KPX Y semicolon -50
+KPX Y period -100
+KPX Y o -100
+KPX Y e -80
+KPX Y comma -100
+KPX Y colon -50
+KPX Y a -90
+KPX Y O -70
+KPX Y A -110
+
+KPX a y -20
+KPX a w -15
+KPX a v -15
+KPX a g -10
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b l -10
+
+KPX c y -10
+KPX c l -20
+KPX c k -20
+KPX c h -10
+
+KPX colon space -40
+
+KPX comma space -40
+KPX comma quoteright -120
+KPX comma quotedblright -120
+
+KPX d y -15
+KPX d w -15
+KPX d v -15
+KPX d d -10
+
+KPX e y -15
+KPX e x -15
+KPX e w -15
+KPX e v -15
+KPX e period 20
+KPX e comma 10
+
+KPX f quoteright 30
+KPX f quotedblright 30
+KPX f period -10
+KPX f o -20
+KPX f e -10
+KPX f comma -10
+
+KPX g g -10
+KPX g e 10
+
+KPX h y -20
+
+KPX k o -15
+
+KPX l y -15
+KPX l w -15
+
+KPX m y -30
+KPX m u -20
+
+KPX n y -20
+KPX n v -40
+KPX n u -10
+
+KPX o y -20
+KPX o x -30
+KPX o w -15
+KPX o v -20
+
+KPX p y -15
+
+KPX period space -40
+KPX period quoteright -120
+KPX period quotedblright -120
+
+KPX quotedblright space -80
+
+KPX quoteleft quoteleft -46
+
+KPX quoteright v -20
+KPX quoteright space -80
+KPX quoteright s -60
+KPX quoteright r -40
+KPX quoteright quoteright -46
+KPX quoteright l -20
+KPX quoteright d -80
+
+KPX r y 10
+KPX r v 10
+KPX r t 20
+KPX r s -15
+KPX r q -20
+KPX r period -60
+KPX r o -20
+KPX r hyphen -20
+KPX r g -15
+KPX r d -20
+KPX r comma -60
+KPX r c -20
+
+KPX s w -15
+
+KPX semicolon space -40
+
+KPX space quoteleft -60
+KPX space quotedblleft -80
+KPX space Y -120
+KPX space W -80
+KPX space V -80
+KPX space T -100
+
+KPX v period -80
+KPX v o -30
+KPX v comma -80
+KPX v a -20
+
+KPX w period -40
+KPX w o -20
+KPX w comma -40
+
+KPX x e -10
+
+KPX y period -80
+KPX y o -25
+KPX y e -10
+KPX y comma -80
+KPX y a -30
+
+KPX z e 10
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 235 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 235 186 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 235 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 235 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 235 186 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 235 186 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 215 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 207 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 207 186 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 207 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 207 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 13 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 13 186 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 13 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 13 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 235 186 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 263 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 263 186 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 263 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 263 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 263 186 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 207 186 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 235 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 235 186 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 235 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 235 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 207 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 207 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 179 186 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 132 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 139 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 139 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 139 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 139 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 112 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 112 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Condensed-Bold.afm b/tlt3.0/library/afm/Helvetica-Condensed-Bold.afm
new file mode 100644
index 0000000..4f0c660
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Condensed-Bold.afm
@@ -0,0 +1,419 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Wed Sep 4 17:42:59 1991
+Comment UniqueID 36188
+Comment VMusage 27402 34294
+FontName Helvetica-Condensed-Bold
+FullName Helvetica Condensed Bold
+FamilyName Helvetica
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -169 -250 1091 991
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 750
+XHeight 564
+Ascender 750
+Descender -189
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 101 0 232 750 ;
+C 34 ; WX 333 ; N quotedbl ; B 16 468 318 739 ;
+C 35 ; WX 500 ; N numbersign ; B 31 0 469 738 ;
+C 36 ; WX 500 ; N dollar ; B 35 -124 466 803 ;
+C 37 ; WX 833 ; N percent ; B 31 -15 803 750 ;
+C 38 ; WX 667 ; N ampersand ; B 63 -18 615 768 ;
+C 39 ; WX 278 ; N quoteright ; B 81 479 202 750 ;
+C 40 ; WX 333 ; N parenleft ; B 52 -198 281 768 ;
+C 41 ; WX 333 ; N parenright ; B 52 -198 281 768 ;
+C 42 ; WX 500 ; N asterisk ; B 79 412 422 738 ;
+C 43 ; WX 500 ; N plus ; B 26 0 475 492 ;
+C 44 ; WX 333 ; N comma ; B 101 -145 233 132 ;
+C 45 ; WX 333 ; N hyphen ; B 48 255 286 370 ;
+C 46 ; WX 333 ; N period ; B 101 0 233 132 ;
+C 47 ; WX 278 ; N slash ; B -11 -94 312 750 ;
+C 48 ; WX 500 ; N zero ; B 48 -15 453 753 ;
+C 49 ; WX 500 ; N one ; B 44 0 353 750 ;
+C 50 ; WX 500 ; N two ; B 32 0 453 753 ;
+C 51 ; WX 500 ; N three ; B 28 -15 453 753 ;
+C 52 ; WX 500 ; N four ; B 23 0 470 738 ;
+C 53 ; WX 500 ; N five ; B 37 -15 458 738 ;
+C 54 ; WX 500 ; N six ; B 42 -15 459 753 ;
+C 55 ; WX 500 ; N seven ; B 32 0 454 738 ;
+C 56 ; WX 500 ; N eight ; B 41 -15 460 753 ;
+C 57 ; WX 500 ; N nine ; B 42 -15 459 753 ;
+C 58 ; WX 278 ; N colon ; B 73 0 205 556 ;
+C 59 ; WX 278 ; N semicolon ; B 73 -145 205 556 ;
+C 60 ; WX 500 ; N less ; B 42 -24 459 527 ;
+C 61 ; WX 500 ; N equal ; B 26 96 475 401 ;
+C 62 ; WX 500 ; N greater ; B 42 -24 459 527 ;
+C 63 ; WX 500 ; N question ; B 51 0 440 768 ;
+C 64 ; WX 833 ; N at ; B 38 -18 795 768 ;
+C 65 ; WX 556 ; N A ; B 9 0 547 750 ;
+C 66 ; WX 556 ; N B ; B 65 0 506 750 ;
+C 67 ; WX 556 ; N C ; B 55 -18 512 768 ;
+C 68 ; WX 611 ; N D ; B 72 0 550 750 ;
+C 69 ; WX 500 ; N E ; B 64 0 458 750 ;
+C 70 ; WX 500 ; N F ; B 73 0 470 750 ;
+C 71 ; WX 611 ; N G ; B 55 -18 542 768 ;
+C 72 ; WX 611 ; N H ; B 68 0 544 750 ;
+C 73 ; WX 278 ; N I ; B 69 0 209 750 ;
+C 74 ; WX 444 ; N J ; B 7 -18 384 750 ;
+C 75 ; WX 556 ; N K ; B 68 0 547 750 ;
+C 76 ; WX 500 ; N L ; B 68 0 468 750 ;
+C 77 ; WX 778 ; N M ; B 67 0 712 750 ;
+C 78 ; WX 611 ; N N ; B 68 0 543 750 ;
+C 79 ; WX 611 ; N O ; B 61 -18 551 768 ;
+C 80 ; WX 556 ; N P ; B 68 0 529 750 ;
+C 81 ; WX 611 ; N Q ; B 61 -71 587 768 ;
+C 82 ; WX 611 ; N R ; B 66 0 567 750 ;
+C 83 ; WX 556 ; N S ; B 49 -18 508 768 ;
+C 84 ; WX 500 ; N T ; B 17 0 484 750 ;
+C 85 ; WX 611 ; N U ; B 68 -18 544 750 ;
+C 86 ; WX 556 ; N V ; B 21 0 536 750 ;
+C 87 ; WX 833 ; N W ; B 24 0 810 750 ;
+C 88 ; WX 556 ; N X ; B 11 0 545 750 ;
+C 89 ; WX 556 ; N Y ; B 12 0 545 750 ;
+C 90 ; WX 500 ; N Z ; B 33 0 468 750 ;
+C 91 ; WX 333 ; N bracketleft ; B 81 -94 280 750 ;
+C 92 ; WX 250 ; N backslash ; B -89 0 340 750 ;
+C 93 ; WX 333 ; N bracketright ; B 53 -94 252 750 ;
+C 94 ; WX 500 ; N asciicircum ; B 10 326 490 750 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 76 495 197 766 ;
+C 97 ; WX 500 ; N a ; B 42 -15 440 579 ;
+C 98 ; WX 500 ; N b ; B 64 -15 444 750 ;
+C 99 ; WX 444 ; N c ; B 49 -15 403 579 ;
+C 100 ; WX 500 ; N d ; B 53 -15 433 750 ;
+C 101 ; WX 500 ; N e ; B 53 -15 443 579 ;
+C 102 ; WX 278 ; N f ; B 21 0 257 750 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 53 -190 433 579 ;
+C 104 ; WX 500 ; N h ; B 61 0 440 750 ;
+C 105 ; WX 278 ; N i ; B 74 0 204 750 ;
+C 106 ; WX 278 ; N j ; B 31 -192 210 750 ;
+C 107 ; WX 444 ; N k ; B 48 0 443 750 ;
+C 108 ; WX 278 ; N l ; B 74 0 204 750 ;
+C 109 ; WX 778 ; N m ; B 66 0 712 579 ;
+C 110 ; WX 500 ; N n ; B 61 0 440 579 ;
+C 111 ; WX 500 ; N o ; B 53 -15 447 579 ;
+C 112 ; WX 500 ; N p ; B 58 -189 438 579 ;
+C 113 ; WX 500 ; N q ; B 50 -188 430 579 ;
+C 114 ; WX 333 ; N r ; B 60 0 319 574 ;
+C 115 ; WX 444 ; N s ; B 28 -15 407 579 ;
+C 116 ; WX 278 ; N t ; B 14 -7 252 719 ;
+C 117 ; WX 500 ; N u ; B 58 -15 431 564 ;
+C 118 ; WX 444 ; N v ; B 10 0 434 564 ;
+C 119 ; WX 667 ; N w ; B 11 0 645 564 ;
+C 120 ; WX 444 ; N x ; B 8 0 436 564 ;
+C 121 ; WX 444 ; N y ; B 5 -195 429 564 ;
+C 122 ; WX 389 ; N z ; B 23 0 367 564 ;
+C 123 ; WX 274 ; N braceleft ; B -32 -92 240 750 ;
+C 124 ; WX 250 ; N bar ; B 75 -250 175 750 ;
+C 125 ; WX 274 ; N braceright ; B 34 -94 306 750 ;
+C 126 ; WX 500 ; N asciitilde ; B 26 153 475 359 ;
+C 161 ; WX 333 ; N exclamdown ; B 102 -170 232 579 ;
+C 162 ; WX 500 ; N cent ; B 72 -122 428 671 ;
+C 163 ; WX 500 ; N sterling ; B 35 -15 487 768 ;
+C 164 ; WX 167 ; N fraction ; B -169 0 331 738 ;
+C 165 ; WX 500 ; N yen ; B -18 0 518 750 ;
+C 166 ; WX 500 ; N florin ; B 9 -185 492 763 ;
+C 167 ; WX 500 ; N section ; B 37 -183 463 768 ;
+C 168 ; WX 500 ; N currency ; B 9 58 492 560 ;
+C 169 ; WX 250 ; N quotesingle ; B 66 468 185 739 ;
+C 170 ; WX 500 ; N quotedblleft ; B 87 495 405 766 ;
+C 171 ; WX 500 ; N guillemotleft ; B 74 62 419 447 ;
+C 172 ; WX 278 ; N guilsinglleft ; B 58 62 215 447 ;
+C 173 ; WX 278 ; N guilsinglright ; B 63 62 220 447 ;
+C 174 ; WX 500 ; N fi ; B 10 0 446 750 ;
+C 175 ; WX 500 ; N fl ; B 10 0 443 750 ;
+C 177 ; WX 500 ; N endash ; B 0 259 500 369 ;
+C 178 ; WX 500 ; N dagger ; B 37 -155 463 768 ;
+C 179 ; WX 500 ; N daggerdbl ; B 35 -161 466 768 ;
+C 180 ; WX 333 ; N periodcentered ; B 101 183 233 315 ;
+C 182 ; WX 550 ; N paragraph ; B 23 -116 526 750 ;
+C 183 ; WX 420 ; N bullet ; B 22 186 398 562 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 87 -138 207 132 ;
+C 185 ; WX 500 ; N quotedblbase ; B 96 -138 413 132 ;
+C 186 ; WX 500 ; N quotedblright ; B 95 479 413 750 ;
+C 187 ; WX 500 ; N guillemotright ; B 81 62 426 447 ;
+C 188 ; WX 1000 ; N ellipsis ; B 101 0 899 132 ;
+C 189 ; WX 1111 ; N perthousand ; B 21 -18 1091 748 ;
+C 191 ; WX 500 ; N questiondown ; B 60 -190 449 579 ;
+C 193 ; WX 333 ; N grave ; B 1 629 250 775 ;
+C 194 ; WX 333 ; N acute ; B 83 629 332 775 ;
+C 195 ; WX 333 ; N circumflex ; B -10 644 343 790 ;
+C 196 ; WX 333 ; N tilde ; B -16 636 350 764 ;
+C 197 ; WX 333 ; N macron ; B -6 666 340 740 ;
+C 198 ; WX 333 ; N breve ; B -1 635 335 780 ;
+C 199 ; WX 333 ; N dotaccent ; B 103 644 230 759 ;
+C 200 ; WX 333 ; N dieresis ; B 5 644 328 759 ;
+C 202 ; WX 333 ; N ring ; B 60 632 273 845 ;
+C 203 ; WX 333 ; N cedilla ; B 39 -228 275 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -17 634 447 780 ;
+C 206 ; WX 333 ; N ogonek ; B 88 -205 278 0 ;
+C 207 ; WX 333 ; N caron ; B -10 634 343 780 ;
+C 208 ; WX 1000 ; N emdash ; B 0 259 1000 369 ;
+C 225 ; WX 778 ; N AE ; B -22 0 750 750 ;
+C 227 ; WX 300 ; N ordfeminine ; B 22 412 281 768 ;
+C 232 ; WX 500 ; N Lslash ; B 0 0 474 750 ;
+C 233 ; WX 611 ; N Oslash ; B 36 -38 578 779 ;
+C 234 ; WX 833 ; N OE ; B 61 -18 792 768 ;
+C 235 ; WX 300 ; N ordmasculine ; B 22 412 278 768 ;
+C 241 ; WX 722 ; N ae ; B 44 -15 672 579 ;
+C 245 ; WX 278 ; N dotlessi ; B 74 0 204 564 ;
+C 248 ; WX 278 ; N lslash ; B 2 0 272 750 ;
+C 249 ; WX 500 ; N oslash ; B 7 -58 492 617 ;
+C 250 ; WX 722 ; N oe ; B 46 -15 678 579 ;
+C 251 ; WX 500 ; N germandbls ; B 60 -15 445 768 ;
+C -1 ; WX 500 ; N ecircumflex ; B 53 -15 443 770 ;
+C -1 ; WX 500 ; N edieresis ; B 53 -15 443 759 ;
+C -1 ; WX 500 ; N aacute ; B 42 -15 440 775 ;
+C -1 ; WX 830 ; N registered ; B 22 -18 808 768 ;
+C -1 ; WX 278 ; N icircumflex ; B -47 0 306 770 ;
+C -1 ; WX 500 ; N udieresis ; B 58 -15 431 759 ;
+C -1 ; WX 500 ; N ograve ; B 53 -15 447 775 ;
+C -1 ; WX 500 ; N uacute ; B 58 -15 431 775 ;
+C -1 ; WX 500 ; N ucircumflex ; B 58 -15 431 780 ;
+C -1 ; WX 556 ; N Aacute ; B 9 0 547 961 ;
+C -1 ; WX 278 ; N igrave ; B -26 0 223 775 ;
+C -1 ; WX 278 ; N Icircumflex ; B -37 0 316 956 ;
+C -1 ; WX 444 ; N ccedilla ; B 49 -228 403 579 ;
+C -1 ; WX 500 ; N adieresis ; B 42 -15 440 759 ;
+C -1 ; WX 500 ; N Ecircumflex ; B 64 0 458 956 ;
+C -1 ; WX 444 ; N scaron ; B 28 -15 407 760 ;
+C -1 ; WX 500 ; N thorn ; B 58 -189 438 750 ;
+C -1 ; WX 860 ; N trademark ; B 1 346 774 750 ;
+C -1 ; WX 500 ; N egrave ; B 53 -15 443 775 ;
+C -1 ; WX 300 ; N threesuperior ; B 12 290 288 751 ;
+C -1 ; WX 389 ; N zcaron ; B 18 0 371 760 ;
+C -1 ; WX 500 ; N atilde ; B 42 -15 440 744 ;
+C -1 ; WX 500 ; N aring ; B 42 -15 440 835 ;
+C -1 ; WX 500 ; N ocircumflex ; B 53 -15 447 770 ;
+C -1 ; WX 500 ; N Edieresis ; B 64 0 458 945 ;
+C -1 ; WX 750 ; N threequarters ; B 12 0 739 751 ;
+C -1 ; WX 444 ; N ydieresis ; B 5 -195 429 759 ;
+C -1 ; WX 444 ; N yacute ; B 5 -195 429 775 ;
+C -1 ; WX 278 ; N iacute ; B 56 0 305 775 ;
+C -1 ; WX 556 ; N Acircumflex ; B 9 0 547 956 ;
+C -1 ; WX 611 ; N Uacute ; B 68 -18 544 961 ;
+C -1 ; WX 500 ; N eacute ; B 53 -15 443 775 ;
+C -1 ; WX 611 ; N Ograve ; B 61 -18 551 961 ;
+C -1 ; WX 500 ; N agrave ; B 42 -15 440 775 ;
+C -1 ; WX 611 ; N Udieresis ; B 68 -18 544 945 ;
+C -1 ; WX 500 ; N acircumflex ; B 42 -15 440 770 ;
+C -1 ; WX 278 ; N Igrave ; B -26 0 223 961 ;
+C -1 ; WX 300 ; N twosuperior ; B 13 300 287 752 ;
+C -1 ; WX 611 ; N Ugrave ; B 68 -18 544 961 ;
+C -1 ; WX 750 ; N onequarter ; B 20 0 729 750 ;
+C -1 ; WX 611 ; N Ucircumflex ; B 68 -18 544 956 ;
+C -1 ; WX 556 ; N Scaron ; B 49 -18 508 946 ;
+C -1 ; WX 278 ; N Idieresis ; B -22 0 301 945 ;
+C -1 ; WX 278 ; N idieresis ; B -22 0 301 759 ;
+C -1 ; WX 500 ; N Egrave ; B 64 0 458 961 ;
+C -1 ; WX 611 ; N Oacute ; B 61 -18 551 961 ;
+C -1 ; WX 500 ; N divide ; B 26 6 475 492 ;
+C -1 ; WX 556 ; N Atilde ; B 9 0 547 930 ;
+C -1 ; WX 556 ; N Aring ; B 9 0 547 991 ;
+C -1 ; WX 611 ; N Odieresis ; B 61 -18 551 945 ;
+C -1 ; WX 556 ; N Adieresis ; B 9 0 547 945 ;
+C -1 ; WX 611 ; N Ntilde ; B 68 0 543 930 ;
+C -1 ; WX 500 ; N Zcaron ; B 33 0 468 946 ;
+C -1 ; WX 556 ; N Thorn ; B 68 0 529 750 ;
+C -1 ; WX 278 ; N Iacute ; B 56 0 305 961 ;
+C -1 ; WX 500 ; N plusminus ; B 26 -15 475 513 ;
+C -1 ; WX 500 ; N multiply ; B 26 22 475 476 ;
+C -1 ; WX 500 ; N Eacute ; B 64 0 458 961 ;
+C -1 ; WX 556 ; N Ydieresis ; B 12 0 545 945 ;
+C -1 ; WX 300 ; N onesuperior ; B 50 300 251 750 ;
+C -1 ; WX 500 ; N ugrave ; B 58 -15 431 775 ;
+C -1 ; WX 500 ; N logicalnot ; B 26 105 475 401 ;
+C -1 ; WX 500 ; N ntilde ; B 61 0 440 744 ;
+C -1 ; WX 611 ; N Otilde ; B 61 -18 551 930 ;
+C -1 ; WX 500 ; N otilde ; B 53 -15 447 744 ;
+C -1 ; WX 556 ; N Ccedilla ; B 55 -228 512 768 ;
+C -1 ; WX 556 ; N Agrave ; B 9 0 547 961 ;
+C -1 ; WX 750 ; N onehalf ; B 12 0 739 750 ;
+C -1 ; WX 611 ; N Eth ; B 20 0 550 750 ;
+C -1 ; WX 400 ; N degree ; B 50 450 350 750 ;
+C -1 ; WX 556 ; N Yacute ; B 12 0 545 961 ;
+C -1 ; WX 611 ; N Ocircumflex ; B 61 -18 551 956 ;
+C -1 ; WX 500 ; N oacute ; B 53 -15 447 775 ;
+C -1 ; WX 500 ; N mu ; B 58 -189 431 564 ;
+C -1 ; WX 500 ; N minus ; B 26 194 475 304 ;
+C -1 ; WX 500 ; N eth ; B 53 -15 447 779 ;
+C -1 ; WX 500 ; N odieresis ; B 53 -15 447 759 ;
+C -1 ; WX 830 ; N copyright ; B 22 -18 808 768 ;
+C -1 ; WX 250 ; N brokenbar ; B 75 -175 175 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 88
+
+KPX A y -18
+KPX A w -18
+KPX A v -18
+KPX A quoteright -55
+KPX A Y -55
+KPX A W -37
+KPX A V -37
+KPX A T -55
+
+KPX F period -111
+KPX F comma -111
+KPX F A -37
+
+KPX L y -37
+KPX L quoteright -92
+KPX L Y -92
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -37
+
+KPX R Y -18
+KPX R T -18
+
+KPX T y -55
+KPX T w -74
+KPX T u -74
+KPX T semicolon -74
+KPX T s -74
+KPX T r -74
+KPX T period -92
+KPX T o -74
+KPX T i -18
+KPX T hyphen -55
+KPX T e -74
+KPX T comma -92
+KPX T colon -74
+KPX T c -74
+KPX T a -74
+KPX T A -55
+
+KPX V u -18
+KPX V semicolon -18
+KPX V r -18
+KPX V period -92
+KPX V o -18
+KPX V hyphen -18
+KPX V e -18
+KPX V comma -92
+KPX V colon -18
+KPX V a -18
+KPX V A -37
+
+KPX W period -74
+KPX W o -18
+KPX W hyphen -18
+KPX W e -18
+KPX W comma -74
+KPX W a -18
+KPX W A -18
+
+KPX Y v -18
+KPX Y u -37
+KPX Y semicolon -37
+KPX Y q -55
+KPX Y period -111
+KPX Y p -37
+KPX Y o -55
+KPX Y i -18
+KPX Y hyphen -74
+KPX Y e -55
+KPX Y comma -111
+KPX Y colon -37
+KPX Y a -55
+KPX Y A -55
+
+KPX f quoteright 18
+
+KPX quoteleft quoteleft -18
+
+KPX quoteright s -55
+KPX quoteright quoteright -18
+
+KPX r z 20
+KPX r y 18
+KPX r x 20
+KPX r w 18
+KPX r v 18
+KPX r period -74
+KPX r hyphen -37
+KPX r comma -74
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -37
+KPX w comma -37
+
+KPX y period -55
+KPX y comma -55
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 112 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 102 166 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 112 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 112 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 112 146 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 112 166 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 84 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 84 166 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 84 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 84 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 166 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 139 166 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 139 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 139 166 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 139 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 139 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 139 166 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 166 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 139 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 139 166 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 139 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 139 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 112 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 112 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 84 166 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 -20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 84 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 84 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 69 -10 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 -20 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 84 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 84 -20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 84 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 84 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -37 -20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 -20 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 -20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 -20 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 46 -20 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 84 -10 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 56 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 28 -20 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Condensed-BoldObl.afm b/tlt3.0/library/afm/Helvetica-Condensed-BoldObl.afm
new file mode 100644
index 0000000..08c7c21
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Condensed-BoldObl.afm
@@ -0,0 +1,419 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Wed Sep 4 17:46:28 1991
+Comment UniqueID 36191
+Comment VMusage 8125 43764
+FontName Helvetica-Condensed-BoldObl
+FullName Helvetica Condensed Bold Oblique
+FamilyName Helvetica
+Weight Bold
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -169 -250 1141 991
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 750
+XHeight 564
+Ascender 750
+Descender -189
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 102 0 390 750 ;
+C 34 ; WX 333 ; N quotedbl ; B 115 468 475 739 ;
+C 35 ; WX 500 ; N numbersign ; B 81 0 580 738 ;
+C 36 ; WX 500 ; N dollar ; B 68 -124 576 803 ;
+C 37 ; WX 833 ; N percent ; B 138 -15 853 750 ;
+C 38 ; WX 667 ; N ampersand ; B 101 -18 676 768 ;
+C 39 ; WX 278 ; N quoteright ; B 183 479 361 750 ;
+C 40 ; WX 333 ; N parenleft ; B 91 -198 442 768 ;
+C 41 ; WX 333 ; N parenright ; B 12 -198 363 768 ;
+C 42 ; WX 500 ; N asterisk ; B 203 412 546 738 ;
+C 43 ; WX 500 ; N plus ; B 67 0 540 492 ;
+C 44 ; WX 333 ; N comma ; B 70 -145 261 132 ;
+C 45 ; WX 333 ; N hyphen ; B 102 255 365 370 ;
+C 46 ; WX 333 ; N period ; B 101 0 261 132 ;
+C 47 ; WX 278 ; N slash ; B -31 -94 471 750 ;
+C 48 ; WX 500 ; N zero ; B 82 -15 576 753 ;
+C 49 ; WX 500 ; N one ; B 155 0 512 750 ;
+C 50 ; WX 500 ; N two ; B 32 0 577 753 ;
+C 51 ; WX 500 ; N three ; B 61 -15 563 753 ;
+C 52 ; WX 500 ; N four ; B 55 0 563 738 ;
+C 53 ; WX 500 ; N five ; B 72 -15 581 738 ;
+C 54 ; WX 500 ; N six ; B 83 -15 575 753 ;
+C 55 ; WX 500 ; N seven ; B 126 0 611 738 ;
+C 56 ; WX 500 ; N eight ; B 76 -15 570 753 ;
+C 57 ; WX 500 ; N nine ; B 84 -15 575 753 ;
+C 58 ; WX 278 ; N colon ; B 73 0 323 556 ;
+C 59 ; WX 278 ; N semicolon ; B 42 -145 323 556 ;
+C 60 ; WX 500 ; N less ; B 85 -24 571 527 ;
+C 61 ; WX 500 ; N equal ; B 46 96 560 401 ;
+C 62 ; WX 500 ; N greater ; B 37 -24 523 527 ;
+C 63 ; WX 500 ; N question ; B 147 0 569 768 ;
+C 64 ; WX 833 ; N at ; B 109 -18 897 768 ;
+C 65 ; WX 556 ; N A ; B 9 0 547 750 ;
+C 66 ; WX 556 ; N B ; B 65 0 615 750 ;
+C 67 ; WX 556 ; N C ; B 99 -18 630 768 ;
+C 68 ; WX 611 ; N D ; B 72 0 662 750 ;
+C 69 ; WX 500 ; N E ; B 64 0 617 750 ;
+C 70 ; WX 500 ; N F ; B 73 0 629 750 ;
+C 71 ; WX 611 ; N G ; B 99 -18 664 768 ;
+C 72 ; WX 611 ; N H ; B 68 0 703 750 ;
+C 73 ; WX 278 ; N I ; B 69 0 368 750 ;
+C 74 ; WX 444 ; N J ; B 36 -18 543 750 ;
+C 75 ; WX 556 ; N K ; B 68 0 697 750 ;
+C 76 ; WX 500 ; N L ; B 68 0 491 750 ;
+C 77 ; WX 778 ; N M ; B 67 0 871 750 ;
+C 78 ; WX 611 ; N N ; B 68 0 702 750 ;
+C 79 ; WX 611 ; N O ; B 105 -18 664 768 ;
+C 80 ; WX 556 ; N P ; B 68 0 651 750 ;
+C 81 ; WX 611 ; N Q ; B 105 -71 664 768 ;
+C 82 ; WX 611 ; N R ; B 66 0 671 750 ;
+C 83 ; WX 556 ; N S ; B 85 -18 613 768 ;
+C 84 ; WX 500 ; N T ; B 153 0 643 750 ;
+C 85 ; WX 611 ; N U ; B 105 -18 703 750 ;
+C 86 ; WX 556 ; N V ; B 180 0 695 750 ;
+C 87 ; WX 833 ; N W ; B 167 0 969 750 ;
+C 88 ; WX 556 ; N X ; B 11 0 698 750 ;
+C 89 ; WX 556 ; N Y ; B 171 0 704 750 ;
+C 90 ; WX 500 ; N Z ; B 33 0 618 750 ;
+C 91 ; WX 333 ; N bracketleft ; B 61 -94 439 750 ;
+C 92 ; WX 250 ; N backslash ; B 70 0 340 750 ;
+C 93 ; WX 333 ; N bracketright ; B 33 -94 411 750 ;
+C 94 ; WX 500 ; N asciicircum ; B 89 326 569 750 ;
+C 95 ; WX 500 ; N underscore ; B -27 -125 484 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 181 495 360 766 ;
+C 97 ; WX 500 ; N a ; B 68 -15 525 579 ;
+C 98 ; WX 500 ; N b ; B 64 -15 534 750 ;
+C 99 ; WX 444 ; N c ; B 79 -15 496 579 ;
+C 100 ; WX 500 ; N d ; B 83 -15 592 750 ;
+C 101 ; WX 500 ; N e ; B 88 -15 530 579 ;
+C 102 ; WX 278 ; N f ; B 71 0 416 750 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 44 -190 553 579 ;
+C 104 ; WX 500 ; N h ; B 61 0 539 750 ;
+C 105 ; WX 278 ; N i ; B 74 0 363 750 ;
+C 106 ; WX 278 ; N j ; B -9 -192 368 750 ;
+C 107 ; WX 444 ; N k ; B 48 0 563 750 ;
+C 108 ; WX 278 ; N l ; B 74 0 363 750 ;
+C 109 ; WX 778 ; N m ; B 66 0 812 579 ;
+C 110 ; WX 500 ; N n ; B 61 0 539 579 ;
+C 111 ; WX 500 ; N o ; B 88 -15 531 579 ;
+C 112 ; WX 500 ; N p ; B 18 -189 528 579 ;
+C 113 ; WX 500 ; N q ; B 80 -188 550 579 ;
+C 114 ; WX 333 ; N r ; B 60 0 441 574 ;
+C 115 ; WX 444 ; N s ; B 56 -15 498 579 ;
+C 116 ; WX 278 ; N t ; B 83 -7 372 719 ;
+C 117 ; WX 500 ; N u ; B 78 -15 551 564 ;
+C 118 ; WX 444 ; N v ; B 130 0 554 564 ;
+C 119 ; WX 667 ; N w ; B 127 0 765 564 ;
+C 120 ; WX 444 ; N x ; B 8 0 553 564 ;
+C 121 ; WX 444 ; N y ; B 36 -195 549 564 ;
+C 122 ; WX 389 ; N z ; B 23 0 487 564 ;
+C 123 ; WX 274 ; N braceleft ; B 37 -92 399 750 ;
+C 124 ; WX 250 ; N bar ; B 22 -250 334 750 ;
+C 125 ; WX 274 ; N braceright ; B 14 -94 375 750 ;
+C 126 ; WX 500 ; N asciitilde ; B 74 153 536 359 ;
+C 161 ; WX 333 ; N exclamdown ; B 66 -170 355 579 ;
+C 162 ; WX 500 ; N cent ; B 103 -122 521 671 ;
+C 163 ; WX 500 ; N sterling ; B 52 -15 603 768 ;
+C 164 ; WX 167 ; N fraction ; B -169 0 488 738 ;
+C 165 ; WX 500 ; N yen ; B 89 0 677 750 ;
+C 166 ; WX 500 ; N florin ; B -28 -185 651 763 ;
+C 167 ; WX 500 ; N section ; B 48 -183 572 768 ;
+C 168 ; WX 500 ; N currency ; B 38 58 594 560 ;
+C 169 ; WX 250 ; N quotesingle ; B 165 468 342 739 ;
+C 170 ; WX 500 ; N quotedblleft ; B 192 495 568 766 ;
+C 171 ; WX 500 ; N guillemotleft ; B 117 62 514 447 ;
+C 172 ; WX 278 ; N guilsinglleft ; B 101 62 310 447 ;
+C 173 ; WX 278 ; N guilsinglright ; B 76 62 285 447 ;
+C 174 ; WX 500 ; N fi ; B 60 0 605 750 ;
+C 175 ; WX 500 ; N fl ; B 60 0 602 750 ;
+C 177 ; WX 500 ; N endash ; B 55 259 578 369 ;
+C 178 ; WX 500 ; N dagger ; B 127 -155 577 768 ;
+C 179 ; WX 500 ; N daggerdbl ; B 51 -161 579 768 ;
+C 180 ; WX 333 ; N periodcentered ; B 140 183 300 315 ;
+C 182 ; WX 550 ; N paragraph ; B 139 -116 685 750 ;
+C 183 ; WX 420 ; N bullet ; B 97 186 482 562 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 58 -138 235 132 ;
+C 185 ; WX 500 ; N quotedblbase ; B 67 -138 441 132 ;
+C 186 ; WX 500 ; N quotedblright ; B 197 479 572 750 ;
+C 187 ; WX 500 ; N guillemotright ; B 94 62 491 447 ;
+C 188 ; WX 1000 ; N ellipsis ; B 101 0 927 132 ;
+C 189 ; WX 1111 ; N perthousand ; B 128 -18 1141 748 ;
+C 191 ; WX 500 ; N questiondown ; B 54 -190 476 579 ;
+C 193 ; WX 333 ; N grave ; B 166 629 384 775 ;
+C 194 ; WX 333 ; N acute ; B 217 629 497 775 ;
+C 195 ; WX 333 ; N circumflex ; B 127 644 480 790 ;
+C 196 ; WX 333 ; N tilde ; B 119 636 512 764 ;
+C 197 ; WX 333 ; N macron ; B 136 666 497 740 ;
+C 198 ; WX 333 ; N breve ; B 161 635 501 780 ;
+C 199 ; WX 333 ; N dotaccent ; B 240 644 391 759 ;
+C 200 ; WX 333 ; N dieresis ; B 142 644 489 759 ;
+C 202 ; WX 333 ; N ring ; B 215 632 432 845 ;
+C 203 ; WX 333 ; N cedilla ; B -4 -228 248 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 118 634 613 780 ;
+C 206 ; WX 333 ; N ogonek ; B 63 -205 256 0 ;
+C 207 ; WX 333 ; N caron ; B 156 634 509 780 ;
+C 208 ; WX 1000 ; N emdash ; B 55 259 1078 369 ;
+C 225 ; WX 778 ; N AE ; B -22 0 909 750 ;
+C 227 ; WX 300 ; N ordfeminine ; B 127 412 421 768 ;
+C 232 ; WX 500 ; N Lslash ; B 49 0 497 750 ;
+C 233 ; WX 611 ; N Oslash ; B 34 -38 736 779 ;
+C 234 ; WX 833 ; N OE ; B 111 -18 951 768 ;
+C 235 ; WX 300 ; N ordmasculine ; B 133 412 417 768 ;
+C 241 ; WX 722 ; N ae ; B 69 -15 762 579 ;
+C 245 ; WX 278 ; N dotlessi ; B 74 0 324 564 ;
+C 248 ; WX 278 ; N lslash ; B 68 0 391 750 ;
+C 249 ; WX 500 ; N oslash ; B 2 -58 616 617 ;
+C 250 ; WX 722 ; N oe ; B 81 -15 763 579 ;
+C 251 ; WX 500 ; N germandbls ; B 60 -15 561 768 ;
+C -1 ; WX 500 ; N ecircumflex ; B 88 -15 560 770 ;
+C -1 ; WX 500 ; N edieresis ; B 88 -15 573 759 ;
+C -1 ; WX 500 ; N aacute ; B 68 -15 581 775 ;
+C -1 ; WX 830 ; N registered ; B 93 -18 897 768 ;
+C -1 ; WX 278 ; N icircumflex ; B 74 0 439 770 ;
+C -1 ; WX 500 ; N udieresis ; B 78 -15 573 759 ;
+C -1 ; WX 500 ; N ograve ; B 88 -15 531 775 ;
+C -1 ; WX 500 ; N uacute ; B 78 -15 581 775 ;
+C -1 ; WX 500 ; N ucircumflex ; B 78 -15 562 780 ;
+C -1 ; WX 556 ; N Aacute ; B 9 0 648 961 ;
+C -1 ; WX 278 ; N igrave ; B 74 0 357 775 ;
+C -1 ; WX 278 ; N Icircumflex ; B 69 0 488 956 ;
+C -1 ; WX 444 ; N ccedilla ; B 66 -228 496 579 ;
+C -1 ; WX 500 ; N adieresis ; B 68 -15 573 759 ;
+C -1 ; WX 500 ; N Ecircumflex ; B 64 0 617 956 ;
+C -1 ; WX 444 ; N scaron ; B 56 -15 551 760 ;
+C -1 ; WX 500 ; N thorn ; B 18 -189 529 750 ;
+C -1 ; WX 860 ; N trademark ; B 144 346 933 750 ;
+C -1 ; WX 500 ; N egrave ; B 88 -15 530 775 ;
+C -1 ; WX 300 ; N threesuperior ; B 96 290 416 751 ;
+C -1 ; WX 389 ; N zcaron ; B 23 0 533 760 ;
+C -1 ; WX 500 ; N atilde ; B 68 -15 592 744 ;
+C -1 ; WX 500 ; N aring ; B 68 -15 525 835 ;
+C -1 ; WX 500 ; N ocircumflex ; B 88 -15 560 770 ;
+C -1 ; WX 500 ; N Edieresis ; B 64 0 617 945 ;
+C -1 ; WX 750 ; N threequarters ; B 96 0 816 751 ;
+C -1 ; WX 444 ; N ydieresis ; B 36 -195 549 759 ;
+C -1 ; WX 444 ; N yacute ; B 36 -195 553 775 ;
+C -1 ; WX 278 ; N iacute ; B 74 0 470 775 ;
+C -1 ; WX 556 ; N Acircumflex ; B 9 0 617 956 ;
+C -1 ; WX 611 ; N Uacute ; B 105 -18 703 961 ;
+C -1 ; WX 500 ; N eacute ; B 88 -15 581 775 ;
+C -1 ; WX 611 ; N Ograve ; B 105 -18 664 961 ;
+C -1 ; WX 500 ; N agrave ; B 68 -15 525 775 ;
+C -1 ; WX 611 ; N Udieresis ; B 105 -18 703 945 ;
+C -1 ; WX 500 ; N acircumflex ; B 68 -15 560 770 ;
+C -1 ; WX 278 ; N Igrave ; B 69 0 396 961 ;
+C -1 ; WX 300 ; N twosuperior ; B 77 300 425 752 ;
+C -1 ; WX 611 ; N Ugrave ; B 105 -18 703 961 ;
+C -1 ; WX 750 ; N onequarter ; B 131 0 788 750 ;
+C -1 ; WX 611 ; N Ucircumflex ; B 105 -18 703 956 ;
+C -1 ; WX 556 ; N Scaron ; B 85 -18 656 946 ;
+C -1 ; WX 278 ; N Idieresis ; B 69 0 502 945 ;
+C -1 ; WX 278 ; N idieresis ; B 74 0 462 759 ;
+C -1 ; WX 500 ; N Egrave ; B 64 0 617 961 ;
+C -1 ; WX 611 ; N Oacute ; B 105 -18 675 961 ;
+C -1 ; WX 500 ; N divide ; B 67 6 540 492 ;
+C -1 ; WX 556 ; N Atilde ; B 9 0 660 930 ;
+C -1 ; WX 556 ; N Aring ; B 9 0 575 991 ;
+C -1 ; WX 611 ; N Odieresis ; B 105 -18 668 945 ;
+C -1 ; WX 556 ; N Adieresis ; B 9 0 641 945 ;
+C -1 ; WX 611 ; N Ntilde ; B 68 0 702 930 ;
+C -1 ; WX 500 ; N Zcaron ; B 33 0 628 946 ;
+C -1 ; WX 556 ; N Thorn ; B 68 0 625 750 ;
+C -1 ; WX 278 ; N Iacute ; B 69 0 509 961 ;
+C -1 ; WX 500 ; N plusminus ; B 23 -15 556 513 ;
+C -1 ; WX 500 ; N multiply ; B 48 22 560 476 ;
+C -1 ; WX 500 ; N Eacute ; B 64 0 620 961 ;
+C -1 ; WX 556 ; N Ydieresis ; B 171 0 704 945 ;
+C -1 ; WX 300 ; N onesuperior ; B 180 300 410 750 ;
+C -1 ; WX 500 ; N ugrave ; B 78 -15 551 775 ;
+C -1 ; WX 500 ; N logicalnot ; B 88 105 560 401 ;
+C -1 ; WX 500 ; N ntilde ; B 61 0 592 744 ;
+C -1 ; WX 611 ; N Otilde ; B 105 -18 687 930 ;
+C -1 ; WX 500 ; N otilde ; B 88 -15 592 744 ;
+C -1 ; WX 556 ; N Ccedilla ; B 99 -228 630 768 ;
+C -1 ; WX 556 ; N Agrave ; B 9 0 547 961 ;
+C -1 ; WX 750 ; N onehalf ; B 108 0 813 750 ;
+C -1 ; WX 611 ; N Eth ; B 72 0 662 750 ;
+C -1 ; WX 400 ; N degree ; B 174 450 481 750 ;
+C -1 ; WX 556 ; N Yacute ; B 171 0 704 961 ;
+C -1 ; WX 611 ; N Ocircumflex ; B 105 -18 664 956 ;
+C -1 ; WX 500 ; N oacute ; B 88 -15 581 775 ;
+C -1 ; WX 500 ; N mu ; B 18 -189 551 564 ;
+C -1 ; WX 500 ; N minus ; B 67 194 540 304 ;
+C -1 ; WX 500 ; N eth ; B 88 -15 540 779 ;
+C -1 ; WX 500 ; N odieresis ; B 88 -15 573 759 ;
+C -1 ; WX 830 ; N copyright ; B 93 -18 897 768 ;
+C -1 ; WX 250 ; N brokenbar ; B 38 -175 318 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 88
+
+KPX A y -18
+KPX A w -18
+KPX A v -18
+KPX A quoteright -55
+KPX A Y -55
+KPX A W -37
+KPX A V -37
+KPX A T -55
+
+KPX F period -111
+KPX F comma -111
+KPX F A -37
+
+KPX L y -37
+KPX L quoteright -92
+KPX L Y -92
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -37
+
+KPX R Y -18
+KPX R T -18
+
+KPX T y -55
+KPX T w -74
+KPX T u -74
+KPX T semicolon -74
+KPX T s -74
+KPX T r -74
+KPX T period -92
+KPX T o -74
+KPX T i -18
+KPX T hyphen -55
+KPX T e -74
+KPX T comma -92
+KPX T colon -74
+KPX T c -74
+KPX T a -74
+KPX T A -55
+
+KPX V u -18
+KPX V semicolon -18
+KPX V r -18
+KPX V period -92
+KPX V o -18
+KPX V hyphen -18
+KPX V e -18
+KPX V comma -92
+KPX V colon -18
+KPX V a -18
+KPX V A -37
+
+KPX W period -74
+KPX W o -18
+KPX W hyphen -18
+KPX W e -18
+KPX W comma -74
+KPX W a -18
+KPX W A -18
+
+KPX Y v -18
+KPX Y u -37
+KPX Y semicolon -37
+KPX Y q -55
+KPX Y period -111
+KPX Y p -37
+KPX Y o -55
+KPX Y i -18
+KPX Y hyphen -74
+KPX Y e -55
+KPX Y comma -111
+KPX Y colon -37
+KPX Y a -55
+KPX Y A -55
+
+KPX f quoteright 18
+
+KPX quoteleft quoteleft -18
+
+KPX quoteright s -55
+KPX quoteright quoteright -18
+
+KPX r z 20
+KPX r y 18
+KPX r x 20
+KPX r w 18
+KPX r v 18
+KPX r period -74
+KPX r hyphen -37
+KPX r comma -74
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -37
+KPX w comma -37
+
+KPX y period -55
+KPX y comma -55
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 152 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 137 166 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 152 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 152 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 143 146 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 147 166 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 124 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 119 166 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 124 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 124 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 13 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 8 166 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 13 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 13 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 174 166 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 179 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 174 166 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 179 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 179 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 174 166 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 147 166 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 179 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 174 166 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 179 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 179 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 152 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 152 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 119 166 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 80 -20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 84 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 84 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 67 -10 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 80 -20 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 84 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 80 -20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 84 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 84 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -41 -20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 80 -20 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 80 -20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 80 -20 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 42 -20 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 82 -10 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 56 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 24 -20 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Condensed-Oblique.afm b/tlt3.0/library/afm/Helvetica-Condensed-Oblique.afm
new file mode 100644
index 0000000..44da649
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Condensed-Oblique.afm
@@ -0,0 +1,421 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Wed Sep 4 17:59:46 1991
+Comment UniqueID 36200
+Comment VMusage 7672 41967
+FontName Helvetica-Condensed-Oblique
+FullName Helvetica Condensed Oblique
+FamilyName Helvetica
+Weight Medium
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -174 -250 1118 990
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.003
+Notice Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 750
+XHeight 556
+Ascender 750
+Descender -188
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 121 0 371 750 ;
+C 34 ; WX 250 ; N quotedbl ; B 153 513 364 739 ;
+C 35 ; WX 500 ; N numbersign ; B 33 0 621 750 ;
+C 36 ; WX 500 ; N dollar ; B 69 -116 569 815 ;
+C 37 ; WX 833 ; N percent ; B 164 -15 803 750 ;
+C 38 ; WX 667 ; N ampersand ; B 111 -18 648 750 ;
+C 39 ; WX 222 ; N quoteright ; B 171 504 317 750 ;
+C 40 ; WX 333 ; N parenleft ; B 115 -215 443 750 ;
+C 41 ; WX 333 ; N parenright ; B 3 -215 331 750 ;
+C 42 ; WX 500 ; N asterisk ; B 229 455 537 750 ;
+C 43 ; WX 500 ; N plus ; B 91 0 518 505 ;
+C 44 ; WX 250 ; N comma ; B 49 -146 192 100 ;
+C 45 ; WX 333 ; N hyphen ; B 103 275 364 358 ;
+C 46 ; WX 250 ; N period ; B 80 0 192 100 ;
+C 47 ; WX 278 ; N slash ; B -19 -27 450 750 ;
+C 48 ; WX 500 ; N zero ; B 98 -15 563 750 ;
+C 49 ; WX 500 ; N one ; B 190 0 476 750 ;
+C 50 ; WX 500 ; N two ; B 44 0 562 750 ;
+C 51 ; WX 500 ; N three ; B 73 -15 552 750 ;
+C 52 ; WX 500 ; N four ; B 68 0 543 750 ;
+C 53 ; WX 500 ; N five ; B 75 -15 575 735 ;
+C 54 ; WX 500 ; N six ; B 91 -15 566 750 ;
+C 55 ; WX 500 ; N seven ; B 116 0 612 735 ;
+C 56 ; WX 500 ; N eight ; B 83 -15 559 750 ;
+C 57 ; WX 500 ; N nine ; B 91 -15 566 750 ;
+C 58 ; WX 250 ; N colon ; B 80 0 287 547 ;
+C 59 ; WX 250 ; N semicolon ; B 49 -146 287 547 ;
+C 60 ; WX 500 ; N less ; B 89 -10 569 518 ;
+C 61 ; WX 500 ; N equal ; B 70 124 539 384 ;
+C 62 ; WX 500 ; N greater ; B 40 -10 520 518 ;
+C 63 ; WX 500 ; N question ; B 169 0 586 750 ;
+C 64 ; WX 800 ; N at ; B 106 -15 863 750 ;
+C 65 ; WX 556 ; N A ; B 11 0 546 750 ;
+C 66 ; WX 556 ; N B ; B 80 0 610 750 ;
+C 67 ; WX 556 ; N C ; B 106 -18 624 765 ;
+C 68 ; WX 611 ; N D ; B 82 0 653 750 ;
+C 69 ; WX 500 ; N E ; B 74 0 608 750 ;
+C 70 ; WX 444 ; N F ; B 74 0 585 750 ;
+C 71 ; WX 611 ; N G ; B 109 -18 646 765 ;
+C 72 ; WX 611 ; N H ; B 79 0 691 750 ;
+C 73 ; WX 278 ; N I ; B 98 0 340 750 ;
+C 74 ; WX 444 ; N J ; B 52 -15 527 750 ;
+C 75 ; WX 556 ; N K ; B 79 0 698 750 ;
+C 76 ; WX 500 ; N L ; B 83 0 488 750 ;
+C 77 ; WX 778 ; N M ; B 76 0 861 750 ;
+C 78 ; WX 611 ; N N ; B 77 0 693 750 ;
+C 79 ; WX 611 ; N O ; B 116 -18 658 765 ;
+C 80 ; WX 556 ; N P ; B 86 0 641 750 ;
+C 81 ; WX 611 ; N Q ; B 116 -34 659 765 ;
+C 82 ; WX 611 ; N R ; B 86 0 655 750 ;
+C 83 ; WX 556 ; N S ; B 86 -18 611 765 ;
+C 84 ; WX 500 ; N T ; B 158 0 645 750 ;
+C 85 ; WX 611 ; N U ; B 114 -18 690 750 ;
+C 86 ; WX 556 ; N V ; B 170 0 704 750 ;
+C 87 ; WX 833 ; N W ; B 176 0 975 750 ;
+C 88 ; WX 556 ; N X ; B 17 0 692 750 ;
+C 89 ; WX 556 ; N Y ; B 170 0 705 750 ;
+C 90 ; WX 500 ; N Z ; B 28 0 627 750 ;
+C 91 ; WX 333 ; N bracketleft ; B 56 -209 434 750 ;
+C 92 ; WX 250 ; N backslash ; B 128 0 281 750 ;
+C 93 ; WX 333 ; N bracketright ; B 14 -209 392 750 ;
+C 94 ; WX 500 ; N asciicircum ; B 141 333 502 750 ;
+C 95 ; WX 500 ; N underscore ; B -27 -125 484 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 175 521 321 767 ;
+C 97 ; WX 444 ; N a ; B 55 -15 465 571 ;
+C 98 ; WX 500 ; N b ; B 75 -15 525 750 ;
+C 99 ; WX 444 ; N c ; B 85 -15 488 571 ;
+C 100 ; WX 500 ; N d ; B 88 -15 583 750 ;
+C 101 ; WX 444 ; N e ; B 86 -15 476 571 ;
+C 102 ; WX 278 ; N f ; B 93 0 418 752 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 53 -189 544 571 ;
+C 104 ; WX 500 ; N h ; B 73 0 524 750 ;
+C 105 ; WX 222 ; N i ; B 72 0 310 750 ;
+C 106 ; WX 222 ; N j ; B -27 -190 313 750 ;
+C 107 ; WX 444 ; N k ; B 69 0 552 750 ;
+C 108 ; WX 222 ; N l ; B 72 0 310 750 ;
+C 109 ; WX 778 ; N m ; B 76 0 799 571 ;
+C 110 ; WX 500 ; N n ; B 73 0 524 571 ;
+C 111 ; WX 500 ; N o ; B 96 -15 524 571 ;
+C 112 ; WX 500 ; N p ; B 32 -188 524 571 ;
+C 113 ; WX 500 ; N q ; B 100 -184 544 571 ;
+C 114 ; WX 333 ; N r ; B 81 0 441 563 ;
+C 115 ; WX 444 ; N s ; B 68 -15 473 571 ;
+C 116 ; WX 278 ; N t ; B 101 0 375 707 ;
+C 117 ; WX 500 ; N u ; B 99 -15 542 556 ;
+C 118 ; WX 444 ; N v ; B 131 0 549 556 ;
+C 119 ; WX 667 ; N w ; B 137 0 767 556 ;
+C 120 ; WX 444 ; N x ; B 9 0 548 556 ;
+C 121 ; WX 444 ; N y ; B -13 -190 543 556 ;
+C 122 ; WX 389 ; N z ; B 24 0 482 556 ;
+C 123 ; WX 274 ; N braceleft ; B 77 -95 425 750 ;
+C 124 ; WX 250 ; N bar ; B 40 -250 316 750 ;
+C 125 ; WX 274 ; N braceright ; B -12 -95 337 750 ;
+C 126 ; WX 500 ; N asciitilde ; B 89 166 520 345 ;
+C 161 ; WX 333 ; N exclamdown ; B 83 -179 333 571 ;
+C 162 ; WX 500 ; N cent ; B 94 -137 499 667 ;
+C 163 ; WX 500 ; N sterling ; B 40 -15 589 750 ;
+C 164 ; WX 167 ; N fraction ; B -174 0 500 750 ;
+C 165 ; WX 500 ; N yen ; B 88 0 677 750 ;
+C 166 ; WX 500 ; N florin ; B -28 -192 645 750 ;
+C 167 ; WX 500 ; N section ; B 51 -208 552 750 ;
+C 168 ; WX 500 ; N currency ; B 51 50 576 553 ;
+C 169 ; WX 250 ; N quotesingle ; B 208 513 308 739 ;
+C 170 ; WX 389 ; N quotedblleft ; B 173 521 490 767 ;
+C 171 ; WX 500 ; N guillemotleft ; B 145 125 520 495 ;
+C 172 ; WX 278 ; N guilsinglleft ; B 124 125 320 495 ;
+C 173 ; WX 278 ; N guilsinglright ; B 90 125 286 495 ;
+C 174 ; WX 500 ; N fi ; B 93 0 584 752 ;
+C 175 ; WX 500 ; N fl ; B 93 0 584 752 ;
+C 177 ; WX 500 ; N endash ; B 58 275 573 345 ;
+C 178 ; WX 500 ; N dagger ; B 137 -176 573 750 ;
+C 179 ; WX 500 ; N daggerdbl ; B 50 -176 572 750 ;
+C 180 ; WX 250 ; N periodcentered ; B 123 204 236 304 ;
+C 182 ; WX 440 ; N paragraph ; B 113 -116 550 750 ;
+C 183 ; WX 333 ; N bullet ; B 91 222 401 529 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 33 -146 179 100 ;
+C 185 ; WX 389 ; N quotedblbase ; B 31 -146 348 100 ;
+C 186 ; WX 389 ; N quotedblright ; B 169 504 486 750 ;
+C 187 ; WX 500 ; N guillemotright ; B 112 125 487 495 ;
+C 188 ; WX 1000 ; N ellipsis ; B 121 0 899 100 ;
+C 189 ; WX 1111 ; N perthousand ; B 157 -16 1118 750 ;
+C 191 ; WX 500 ; N questiondown ; B 33 -190 450 559 ;
+C 193 ; WX 333 ; N grave ; B 198 624 366 765 ;
+C 194 ; WX 333 ; N acute ; B 233 624 461 765 ;
+C 195 ; WX 333 ; N circumflex ; B 154 624 446 765 ;
+C 196 ; WX 333 ; N tilde ; B 132 633 496 749 ;
+C 197 ; WX 333 ; N macron ; B 150 657 475 715 ;
+C 198 ; WX 333 ; N breve ; B 172 629 484 765 ;
+C 199 ; WX 250 ; N dotaccent ; B 224 650 324 750 ;
+C 200 ; WX 333 ; N dieresis ; B 190 650 440 750 ;
+C 202 ; WX 250 ; N ring ; B 169 593 377 796 ;
+C 203 ; WX 333 ; N cedilla ; B 23 -224 255 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 194 624 603 765 ;
+C 206 ; WX 333 ; N ogonek ; B -23 -191 188 13 ;
+C 207 ; WX 333 ; N caron ; B 184 624 476 765 ;
+C 208 ; WX 1000 ; N emdash ; B 58 275 1073 345 ;
+C 225 ; WX 833 ; N AE ; B 0 0 944 750 ;
+C 227 ; WX 300 ; N ordfeminine ; B 129 413 392 765 ;
+C 232 ; WX 500 ; N Lslash ; B 39 0 488 750 ;
+C 233 ; WX 611 ; N Oslash ; B 25 -43 738 796 ;
+C 234 ; WX 833 ; N OE ; B 113 -18 946 765 ;
+C 235 ; WX 300 ; N ordmasculine ; B 138 413 413 765 ;
+C 241 ; WX 667 ; N ae ; B 50 -15 711 571 ;
+C 245 ; WX 222 ; N dotlessi ; B 72 0 269 556 ;
+C 248 ; WX 222 ; N lslash ; B 59 0 347 750 ;
+C 249 ; WX 500 ; N oslash ; B 19 -46 591 582 ;
+C 250 ; WX 722 ; N oe ; B 81 -15 758 571 ;
+C 251 ; WX 500 ; N germandbls ; B 71 -5 548 765 ;
+C -1 ; WX 444 ; N ecircumflex ; B 86 -15 502 765 ;
+C -1 ; WX 444 ; N edieresis ; B 86 -15 496 750 ;
+C -1 ; WX 444 ; N aacute ; B 55 -15 517 765 ;
+C -1 ; WX 800 ; N registered ; B 79 -18 881 765 ;
+C -1 ; WX 222 ; N icircumflex ; B 72 0 391 765 ;
+C -1 ; WX 500 ; N udieresis ; B 99 -15 542 750 ;
+C -1 ; WX 500 ; N ograve ; B 96 -15 524 765 ;
+C -1 ; WX 500 ; N uacute ; B 99 -15 545 765 ;
+C -1 ; WX 500 ; N ucircumflex ; B 99 -15 542 765 ;
+C -1 ; WX 556 ; N Aacute ; B 11 0 614 959 ;
+C -1 ; WX 222 ; N igrave ; B 72 0 311 765 ;
+C -1 ; WX 278 ; N Icircumflex ; B 98 0 460 959 ;
+C -1 ; WX 444 ; N ccedilla ; B 79 -224 488 571 ;
+C -1 ; WX 444 ; N adieresis ; B 55 -15 496 750 ;
+C -1 ; WX 500 ; N Ecircumflex ; B 74 0 608 959 ;
+C -1 ; WX 444 ; N scaron ; B 68 -15 532 765 ;
+C -1 ; WX 500 ; N thorn ; B 32 -188 523 750 ;
+C -1 ; WX 750 ; N trademark ; B 147 329 878 750 ;
+C -1 ; WX 444 ; N egrave ; B 86 -15 476 765 ;
+C -1 ; WX 300 ; N threesuperior ; B 102 291 409 750 ;
+C -1 ; WX 389 ; N zcaron ; B 24 0 504 765 ;
+C -1 ; WX 444 ; N atilde ; B 55 -15 552 749 ;
+C -1 ; WX 444 ; N aring ; B 55 -15 465 826 ;
+C -1 ; WX 500 ; N ocircumflex ; B 96 -15 530 765 ;
+C -1 ; WX 500 ; N Edieresis ; B 74 0 608 944 ;
+C -1 ; WX 750 ; N threequarters ; B 106 0 831 750 ;
+C -1 ; WX 444 ; N ydieresis ; B -13 -190 543 750 ;
+C -1 ; WX 444 ; N yacute ; B -13 -190 543 765 ;
+C -1 ; WX 222 ; N iacute ; B 72 0 406 765 ;
+C -1 ; WX 556 ; N Acircumflex ; B 11 0 599 959 ;
+C -1 ; WX 611 ; N Uacute ; B 114 -18 690 959 ;
+C -1 ; WX 444 ; N eacute ; B 86 -15 517 765 ;
+C -1 ; WX 611 ; N Ograve ; B 116 -18 658 959 ;
+C -1 ; WX 444 ; N agrave ; B 55 -15 465 765 ;
+C -1 ; WX 611 ; N Udieresis ; B 114 -18 690 944 ;
+C -1 ; WX 444 ; N acircumflex ; B 55 -15 502 765 ;
+C -1 ; WX 278 ; N Igrave ; B 98 0 380 959 ;
+C -1 ; WX 300 ; N twosuperior ; B 83 300 413 750 ;
+C -1 ; WX 611 ; N Ugrave ; B 114 -18 690 959 ;
+C -1 ; WX 750 ; N onequarter ; B 143 0 817 750 ;
+C -1 ; WX 611 ; N Ucircumflex ; B 114 -18 690 959 ;
+C -1 ; WX 556 ; N Scaron ; B 86 -18 629 959 ;
+C -1 ; WX 278 ; N Idieresis ; B 98 0 455 944 ;
+C -1 ; WX 222 ; N idieresis ; B 72 0 385 750 ;
+C -1 ; WX 500 ; N Egrave ; B 74 0 608 959 ;
+C -1 ; WX 611 ; N Oacute ; B 116 -18 658 959 ;
+C -1 ; WX 500 ; N divide ; B 91 3 518 505 ;
+C -1 ; WX 556 ; N Atilde ; B 11 0 649 943 ;
+C -1 ; WX 556 ; N Aring ; B 11 0 571 990 ;
+C -1 ; WX 611 ; N Odieresis ; B 116 -18 658 944 ;
+C -1 ; WX 556 ; N Adieresis ; B 11 0 594 944 ;
+C -1 ; WX 611 ; N Ntilde ; B 77 0 693 943 ;
+C -1 ; WX 500 ; N Zcaron ; B 28 0 627 959 ;
+C -1 ; WX 556 ; N Thorn ; B 86 0 618 750 ;
+C -1 ; WX 278 ; N Iacute ; B 98 0 475 959 ;
+C -1 ; WX 500 ; N plusminus ; B 44 0 531 505 ;
+C -1 ; WX 500 ; N multiply ; B 65 48 544 461 ;
+C -1 ; WX 500 ; N Eacute ; B 74 0 608 959 ;
+C -1 ; WX 556 ; N Ydieresis ; B 170 0 705 944 ;
+C -1 ; WX 300 ; N onesuperior ; B 200 300 392 750 ;
+C -1 ; WX 500 ; N ugrave ; B 99 -15 542 765 ;
+C -1 ; WX 500 ; N logicalnot ; B 111 117 539 384 ;
+C -1 ; WX 500 ; N ntilde ; B 73 0 580 749 ;
+C -1 ; WX 611 ; N Otilde ; B 116 -18 676 943 ;
+C -1 ; WX 500 ; N otilde ; B 96 -15 580 749 ;
+C -1 ; WX 556 ; N Ccedilla ; B 106 -224 624 765 ;
+C -1 ; WX 556 ; N Agrave ; B 11 0 546 959 ;
+C -1 ; WX 750 ; N onehalf ; B 91 0 777 750 ;
+C -1 ; WX 611 ; N Eth ; B 82 0 650 750 ;
+C -1 ; WX 400 ; N degree ; B 174 450 481 750 ;
+C -1 ; WX 556 ; N Yacute ; B 170 0 705 959 ;
+C -1 ; WX 611 ; N Ocircumflex ; B 116 -18 658 959 ;
+C -1 ; WX 500 ; N oacute ; B 96 -15 545 765 ;
+C -1 ; WX 500 ; N mu ; B 35 -189 540 556 ;
+C -1 ; WX 500 ; N minus ; B 91 219 518 289 ;
+C -1 ; WX 500 ; N eth ; B 96 -15 525 831 ;
+C -1 ; WX 500 ; N odieresis ; B 96 -15 524 750 ;
+C -1 ; WX 800 ; N copyright ; B 79 -18 880 765 ;
+C -1 ; WX 250 ; N brokenbar ; B 56 -175 300 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 90
+
+KPX A y -18
+KPX A w -18
+KPX A v -18
+KPX A quoteright -55
+KPX A Y -55
+KPX A W -37
+KPX A V -37
+KPX A T -55
+
+KPX F period -111
+KPX F comma -111
+KPX F A -37
+
+KPX L y -37
+KPX L quoteright -92
+KPX L Y -92
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -37
+
+KPX R Y -18
+KPX R T -18
+
+KPX T y -55
+KPX T w -74
+KPX T u -74
+KPX T semicolon -74
+KPX T s -74
+KPX T r -74
+KPX T period -92
+KPX T o -74
+KPX T i -18
+KPX T hyphen -55
+KPX T e -74
+KPX T comma -92
+KPX T colon -74
+KPX T c -74
+KPX T a -74
+KPX T A -55
+
+KPX V u -18
+KPX V semicolon -18
+KPX V r -18
+KPX V period -92
+KPX V o -18
+KPX V hyphen -18
+KPX V e -18
+KPX V comma -92
+KPX V colon -18
+KPX V a -18
+KPX V A -37
+
+KPX W period -74
+KPX W o -18
+KPX W hyphen -18
+KPX W e -18
+KPX W comma -74
+KPX W a -18
+KPX W A -18
+
+KPX Y v -18
+KPX Y u -37
+KPX Y semicolon -37
+KPX Y q -55
+KPX Y period -111
+KPX Y p -37
+KPX Y o -55
+KPX Y i -18
+KPX Y hyphen -74
+KPX Y e -55
+KPX Y comma -111
+KPX Y colon -37
+KPX Y a -55
+KPX Y A -55
+
+KPX f quoteright 18
+
+KPX quoteleft quoteleft -18
+
+KPX quoteright s -55
+KPX quoteright quoteright -18
+
+KPX r z 20
+KPX r y 18
+KPX r x 20
+KPX r w 18
+KPX r v 18
+KPX r period -74
+KPX r hyphen -37
+KPX r f 20
+KPX r comma -74
+KPX r c -20
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -37
+KPX w comma -37
+
+KPX y period -55
+KPX y comma -55
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 153 194 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 153 194 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 153 194 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 153 194 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 194 194 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 153 194 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 125 194 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 125 194 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 125 194 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 125 194 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 14 194 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 14 194 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 14 194 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 14 194 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 180 194 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 180 194 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 180 194 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 180 194 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 180 194 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 180 194 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 153 194 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 180 194 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 180 194 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 180 194 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 180 194 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 153 194 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 153 194 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 125 194 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 56 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 56 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 56 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 56 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 88 30 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -55 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -55 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -55 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -55 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 56 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 84 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 56 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 28 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Condensed.afm b/tlt3.0/library/afm/Helvetica-Condensed.afm
new file mode 100644
index 0000000..f22040c
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Condensed.afm
@@ -0,0 +1,421 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Wed Sep 4 17:26:31 1991
+Comment UniqueID 36179
+Comment VMusage 26415 33307
+FontName Helvetica-Condensed
+FullName Helvetica Condensed Medium
+FamilyName Helvetica
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -174 -250 1071 990
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.003
+Notice Copyright (c) 1985, 1987, 1991 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 750
+XHeight 556
+Ascender 750
+Descender -188
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 121 0 212 750 ;
+C 34 ; WX 250 ; N quotedbl ; B 44 513 207 739 ;
+C 35 ; WX 500 ; N numbersign ; B 5 0 495 750 ;
+C 36 ; WX 500 ; N dollar ; B 35 -116 465 815 ;
+C 37 ; WX 833 ; N percent ; B 55 -15 756 750 ;
+C 38 ; WX 667 ; N ampersand ; B 75 -18 620 750 ;
+C 39 ; WX 222 ; N quoteright ; B 64 504 158 750 ;
+C 40 ; WX 333 ; N parenleft ; B 76 -215 289 750 ;
+C 41 ; WX 333 ; N parenright ; B 44 -215 257 750 ;
+C 42 ; WX 500 ; N asterisk ; B 96 455 405 750 ;
+C 43 ; WX 500 ; N plus ; B 44 0 457 505 ;
+C 44 ; WX 250 ; N comma ; B 80 -146 171 100 ;
+C 45 ; WX 333 ; N hyphen ; B 45 275 288 358 ;
+C 46 ; WX 250 ; N period ; B 80 0 171 100 ;
+C 47 ; WX 278 ; N slash ; B -13 -27 291 750 ;
+C 48 ; WX 500 ; N zero ; B 46 -15 455 750 ;
+C 49 ; WX 500 ; N one ; B 74 0 317 750 ;
+C 50 ; WX 500 ; N two ; B 44 0 447 750 ;
+C 51 ; WX 500 ; N three ; B 38 -15 447 750 ;
+C 52 ; WX 500 ; N four ; B 28 0 451 750 ;
+C 53 ; WX 500 ; N five ; B 43 -15 446 735 ;
+C 54 ; WX 500 ; N six ; B 43 -15 458 750 ;
+C 55 ; WX 500 ; N seven ; B 44 0 456 735 ;
+C 56 ; WX 500 ; N eight ; B 46 -15 454 750 ;
+C 57 ; WX 500 ; N nine ; B 43 -15 458 750 ;
+C 58 ; WX 250 ; N colon ; B 80 0 171 547 ;
+C 59 ; WX 250 ; N semicolon ; B 80 -146 171 547 ;
+C 60 ; WX 500 ; N less ; B 42 -10 459 518 ;
+C 61 ; WX 500 ; N equal ; B 44 124 457 384 ;
+C 62 ; WX 500 ; N greater ; B 42 -10 459 518 ;
+C 63 ; WX 500 ; N question ; B 60 0 462 750 ;
+C 64 ; WX 800 ; N at ; B 36 -15 764 750 ;
+C 65 ; WX 556 ; N A ; B 11 0 546 750 ;
+C 66 ; WX 556 ; N B ; B 80 0 503 750 ;
+C 67 ; WX 556 ; N C ; B 53 -18 503 765 ;
+C 68 ; WX 611 ; N D ; B 82 0 548 750 ;
+C 69 ; WX 500 ; N E ; B 74 0 451 750 ;
+C 70 ; WX 444 ; N F ; B 74 0 426 750 ;
+C 71 ; WX 611 ; N G ; B 54 -18 532 765 ;
+C 72 ; WX 611 ; N H ; B 79 0 532 750 ;
+C 73 ; WX 278 ; N I ; B 98 0 181 750 ;
+C 74 ; WX 444 ; N J ; B 21 -15 368 750 ;
+C 75 ; WX 556 ; N K ; B 79 0 546 750 ;
+C 76 ; WX 500 ; N L ; B 83 0 472 750 ;
+C 77 ; WX 778 ; N M ; B 76 0 702 750 ;
+C 78 ; WX 611 ; N N ; B 77 0 534 750 ;
+C 79 ; WX 611 ; N O ; B 59 -18 553 765 ;
+C 80 ; WX 556 ; N P ; B 86 0 519 750 ;
+C 81 ; WX 611 ; N Q ; B 59 -34 582 765 ;
+C 82 ; WX 611 ; N R ; B 86 0 565 750 ;
+C 83 ; WX 556 ; N S ; B 51 -18 505 765 ;
+C 84 ; WX 500 ; N T ; B 15 0 486 750 ;
+C 85 ; WX 611 ; N U ; B 81 -18 531 750 ;
+C 86 ; WX 556 ; N V ; B 11 0 545 750 ;
+C 87 ; WX 833 ; N W ; B 17 0 816 750 ;
+C 88 ; WX 556 ; N X ; B 17 0 539 750 ;
+C 89 ; WX 556 ; N Y ; B 11 0 546 750 ;
+C 90 ; WX 500 ; N Z ; B 28 0 473 750 ;
+C 91 ; WX 333 ; N bracketleft ; B 100 -209 275 750 ;
+C 92 ; WX 250 ; N backslash ; B -31 0 281 750 ;
+C 93 ; WX 333 ; N bracketright ; B 58 -209 233 750 ;
+C 94 ; WX 500 ; N asciicircum ; B 70 333 431 750 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 64 521 158 767 ;
+C 97 ; WX 444 ; N a ; B 31 -15 417 571 ;
+C 98 ; WX 500 ; N b ; B 75 -15 447 750 ;
+C 99 ; WX 444 ; N c ; B 44 -15 405 571 ;
+C 100 ; WX 500 ; N d ; B 48 -15 424 750 ;
+C 101 ; WX 444 ; N e ; B 43 -15 395 571 ;
+C 102 ; WX 278 ; N f ; B 12 0 259 752 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 45 -189 426 571 ;
+C 104 ; WX 500 ; N h ; B 73 0 428 750 ;
+C 105 ; WX 222 ; N i ; B 72 0 151 750 ;
+C 106 ; WX 222 ; N j ; B 13 -190 154 750 ;
+C 107 ; WX 444 ; N k ; B 69 0 439 750 ;
+C 108 ; WX 222 ; N l ; B 72 0 151 750 ;
+C 109 ; WX 778 ; N m ; B 76 0 703 571 ;
+C 110 ; WX 500 ; N n ; B 73 0 428 571 ;
+C 111 ; WX 500 ; N o ; B 51 -15 449 571 ;
+C 112 ; WX 500 ; N p ; B 72 -188 447 571 ;
+C 113 ; WX 500 ; N q ; B 55 -184 426 571 ;
+C 114 ; WX 333 ; N r ; B 81 0 322 563 ;
+C 115 ; WX 444 ; N s ; B 43 -15 400 571 ;
+C 116 ; WX 278 ; N t ; B 9 0 257 707 ;
+C 117 ; WX 500 ; N u ; B 77 -15 424 556 ;
+C 118 ; WX 444 ; N v ; B 13 0 431 556 ;
+C 119 ; WX 667 ; N w ; B 19 0 649 556 ;
+C 120 ; WX 444 ; N x ; B 9 0 436 556 ;
+C 121 ; WX 444 ; N y ; B 5 -190 425 556 ;
+C 122 ; WX 389 ; N z ; B 24 0 366 556 ;
+C 123 ; WX 274 ; N braceleft ; B 7 -95 266 750 ;
+C 124 ; WX 250 ; N bar ; B 93 -250 157 750 ;
+C 125 ; WX 274 ; N braceright ; B 8 -95 267 750 ;
+C 126 ; WX 500 ; N asciitilde ; B 44 166 457 345 ;
+C 161 ; WX 333 ; N exclamdown ; B 121 -179 212 571 ;
+C 162 ; WX 500 ; N cent ; B 58 -137 418 667 ;
+C 163 ; WX 500 ; N sterling ; B 30 -15 485 750 ;
+C 164 ; WX 167 ; N fraction ; B -174 0 341 750 ;
+C 165 ; WX 500 ; N yen ; B -17 0 518 750 ;
+C 166 ; WX 500 ; N florin ; B 10 -192 488 750 ;
+C 167 ; WX 500 ; N section ; B 35 -208 466 750 ;
+C 168 ; WX 500 ; N currency ; B 24 50 475 553 ;
+C 169 ; WX 250 ; N quotesingle ; B 99 513 151 739 ;
+C 170 ; WX 389 ; N quotedblleft ; B 62 521 327 767 ;
+C 171 ; WX 500 ; N guillemotleft ; B 85 125 415 495 ;
+C 172 ; WX 278 ; N guilsinglleft ; B 64 125 215 495 ;
+C 173 ; WX 278 ; N guilsinglright ; B 63 125 214 495 ;
+C 174 ; WX 500 ; N fi ; B 12 0 427 752 ;
+C 175 ; WX 500 ; N fl ; B 12 0 425 752 ;
+C 177 ; WX 500 ; N endash ; B 0 275 500 345 ;
+C 178 ; WX 500 ; N dagger ; B 40 -176 461 750 ;
+C 179 ; WX 500 ; N daggerdbl ; B 39 -176 462 750 ;
+C 180 ; WX 250 ; N periodcentered ; B 80 204 171 304 ;
+C 182 ; WX 440 ; N paragraph ; B 0 -116 391 750 ;
+C 183 ; WX 333 ; N bullet ; B 15 222 318 529 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 64 -146 158 100 ;
+C 185 ; WX 389 ; N quotedblbase ; B 62 -146 327 100 ;
+C 186 ; WX 389 ; N quotedblright ; B 62 504 327 750 ;
+C 187 ; WX 500 ; N guillemotright ; B 85 125 415 495 ;
+C 188 ; WX 1000 ; N ellipsis ; B 121 0 878 100 ;
+C 189 ; WX 1111 ; N perthousand ; B 47 -16 1071 750 ;
+C 191 ; WX 500 ; N questiondown ; B 38 -190 440 559 ;
+C 193 ; WX 333 ; N grave ; B 35 624 233 765 ;
+C 194 ; WX 333 ; N acute ; B 100 624 298 765 ;
+C 195 ; WX 333 ; N circumflex ; B 21 624 313 765 ;
+C 196 ; WX 333 ; N tilde ; B -3 633 337 749 ;
+C 197 ; WX 333 ; N macron ; B 10 657 323 715 ;
+C 198 ; WX 333 ; N breve ; B 12 629 321 765 ;
+C 199 ; WX 250 ; N dotaccent ; B 86 650 165 750 ;
+C 200 ; WX 333 ; N dieresis ; B 52 650 281 750 ;
+C 202 ; WX 250 ; N ring ; B 23 593 227 796 ;
+C 203 ; WX 333 ; N cedilla ; B 66 -224 281 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 61 624 440 765 ;
+C 206 ; WX 333 ; N ogonek ; B 0 -191 208 13 ;
+C 207 ; WX 333 ; N caron ; B 21 624 313 765 ;
+C 208 ; WX 1000 ; N emdash ; B 0 275 1000 345 ;
+C 225 ; WX 833 ; N AE ; B 0 0 785 750 ;
+C 227 ; WX 300 ; N ordfeminine ; B 25 413 276 765 ;
+C 232 ; WX 500 ; N Lslash ; B -13 0 472 750 ;
+C 233 ; WX 611 ; N Oslash ; B 29 -43 573 796 ;
+C 234 ; WX 833 ; N OE ; B 56 -18 787 765 ;
+C 235 ; WX 300 ; N ordmasculine ; B 20 413 279 765 ;
+C 241 ; WX 667 ; N ae ; B 26 -15 630 571 ;
+C 245 ; WX 222 ; N dotlessi ; B 72 0 151 556 ;
+C 248 ; WX 222 ; N lslash ; B -8 0 231 750 ;
+C 249 ; WX 500 ; N oslash ; B 25 -46 472 582 ;
+C 250 ; WX 722 ; N oe ; B 40 -15 676 571 ;
+C 251 ; WX 500 ; N germandbls ; B 71 -5 445 765 ;
+C -1 ; WX 444 ; N ecircumflex ; B 43 -15 395 765 ;
+C -1 ; WX 444 ; N edieresis ; B 43 -15 395 750 ;
+C -1 ; WX 444 ; N aacute ; B 31 -15 417 765 ;
+C -1 ; WX 800 ; N registered ; B 8 -18 792 765 ;
+C -1 ; WX 222 ; N icircumflex ; B -34 0 258 765 ;
+C -1 ; WX 500 ; N udieresis ; B 77 -15 424 750 ;
+C -1 ; WX 500 ; N ograve ; B 51 -15 449 765 ;
+C -1 ; WX 500 ; N uacute ; B 77 -15 424 765 ;
+C -1 ; WX 500 ; N ucircumflex ; B 77 -15 424 765 ;
+C -1 ; WX 556 ; N Aacute ; B 11 0 546 959 ;
+C -1 ; WX 222 ; N igrave ; B -20 0 178 765 ;
+C -1 ; WX 278 ; N Icircumflex ; B -6 0 286 959 ;
+C -1 ; WX 444 ; N ccedilla ; B 44 -224 405 571 ;
+C -1 ; WX 444 ; N adieresis ; B 31 -15 417 750 ;
+C -1 ; WX 500 ; N Ecircumflex ; B 74 0 451 959 ;
+C -1 ; WX 444 ; N scaron ; B 43 -15 400 765 ;
+C -1 ; WX 500 ; N thorn ; B 72 -188 447 750 ;
+C -1 ; WX 750 ; N trademark ; B 0 329 719 750 ;
+C -1 ; WX 444 ; N egrave ; B 43 -15 395 765 ;
+C -1 ; WX 300 ; N threesuperior ; B 17 291 283 750 ;
+C -1 ; WX 389 ; N zcaron ; B 24 0 366 765 ;
+C -1 ; WX 444 ; N atilde ; B 31 -15 417 749 ;
+C -1 ; WX 444 ; N aring ; B 31 -15 417 826 ;
+C -1 ; WX 500 ; N ocircumflex ; B 51 -15 449 765 ;
+C -1 ; WX 500 ; N Edieresis ; B 74 0 451 944 ;
+C -1 ; WX 750 ; N threequarters ; B 21 0 730 750 ;
+C -1 ; WX 444 ; N ydieresis ; B 5 -190 425 750 ;
+C -1 ; WX 444 ; N yacute ; B 5 -190 425 765 ;
+C -1 ; WX 222 ; N iacute ; B 45 0 243 765 ;
+C -1 ; WX 556 ; N Acircumflex ; B 11 0 546 959 ;
+C -1 ; WX 611 ; N Uacute ; B 81 -18 531 959 ;
+C -1 ; WX 444 ; N eacute ; B 43 -15 395 765 ;
+C -1 ; WX 611 ; N Ograve ; B 59 -18 553 959 ;
+C -1 ; WX 444 ; N agrave ; B 31 -15 417 765 ;
+C -1 ; WX 611 ; N Udieresis ; B 81 -18 531 944 ;
+C -1 ; WX 444 ; N acircumflex ; B 31 -15 417 765 ;
+C -1 ; WX 278 ; N Igrave ; B 8 0 206 959 ;
+C -1 ; WX 300 ; N twosuperior ; B 19 300 281 750 ;
+C -1 ; WX 611 ; N Ugrave ; B 81 -18 531 959 ;
+C -1 ; WX 750 ; N onequarter ; B 34 0 716 750 ;
+C -1 ; WX 611 ; N Ucircumflex ; B 81 -18 531 959 ;
+C -1 ; WX 556 ; N Scaron ; B 51 -18 505 959 ;
+C -1 ; WX 278 ; N Idieresis ; B 25 0 254 944 ;
+C -1 ; WX 222 ; N idieresis ; B -3 0 226 750 ;
+C -1 ; WX 500 ; N Egrave ; B 74 0 451 959 ;
+C -1 ; WX 611 ; N Oacute ; B 59 -18 553 959 ;
+C -1 ; WX 500 ; N divide ; B 44 3 457 505 ;
+C -1 ; WX 556 ; N Atilde ; B 11 0 546 943 ;
+C -1 ; WX 556 ; N Aring ; B 11 0 546 990 ;
+C -1 ; WX 611 ; N Odieresis ; B 59 -18 553 944 ;
+C -1 ; WX 556 ; N Adieresis ; B 11 0 546 944 ;
+C -1 ; WX 611 ; N Ntilde ; B 77 0 534 943 ;
+C -1 ; WX 500 ; N Zcaron ; B 28 0 473 959 ;
+C -1 ; WX 556 ; N Thorn ; B 86 0 519 750 ;
+C -1 ; WX 278 ; N Iacute ; B 73 0 271 959 ;
+C -1 ; WX 500 ; N plusminus ; B 44 0 457 505 ;
+C -1 ; WX 500 ; N multiply ; B 44 48 457 461 ;
+C -1 ; WX 500 ; N Eacute ; B 74 0 451 959 ;
+C -1 ; WX 556 ; N Ydieresis ; B 11 0 546 944 ;
+C -1 ; WX 300 ; N onesuperior ; B 67 300 233 750 ;
+C -1 ; WX 500 ; N ugrave ; B 77 -15 424 765 ;
+C -1 ; WX 500 ; N logicalnot ; B 44 117 457 384 ;
+C -1 ; WX 500 ; N ntilde ; B 73 0 428 749 ;
+C -1 ; WX 611 ; N Otilde ; B 59 -18 553 943 ;
+C -1 ; WX 500 ; N otilde ; B 51 -15 449 749 ;
+C -1 ; WX 556 ; N Ccedilla ; B 53 -224 503 765 ;
+C -1 ; WX 556 ; N Agrave ; B 11 0 546 959 ;
+C -1 ; WX 750 ; N onehalf ; B 42 0 709 750 ;
+C -1 ; WX 611 ; N Eth ; B 9 0 548 750 ;
+C -1 ; WX 400 ; N degree ; B 50 450 350 750 ;
+C -1 ; WX 556 ; N Yacute ; B 11 0 546 959 ;
+C -1 ; WX 611 ; N Ocircumflex ; B 59 -18 553 959 ;
+C -1 ; WX 500 ; N oacute ; B 51 -15 449 765 ;
+C -1 ; WX 500 ; N mu ; B 75 -189 422 556 ;
+C -1 ; WX 500 ; N minus ; B 44 219 457 289 ;
+C -1 ; WX 500 ; N eth ; B 51 -15 449 831 ;
+C -1 ; WX 500 ; N odieresis ; B 51 -15 449 750 ;
+C -1 ; WX 800 ; N copyright ; B 8 -18 792 765 ;
+C -1 ; WX 250 ; N brokenbar ; B 93 -175 157 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 90
+
+KPX A y -18
+KPX A w -18
+KPX A v -18
+KPX A quoteright -55
+KPX A Y -55
+KPX A W -37
+KPX A V -37
+KPX A T -55
+
+KPX F period -111
+KPX F comma -111
+KPX F A -37
+
+KPX L y -37
+KPX L quoteright -92
+KPX L Y -92
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -37
+
+KPX R Y -18
+KPX R T -18
+
+KPX T y -55
+KPX T w -74
+KPX T u -74
+KPX T semicolon -74
+KPX T s -74
+KPX T r -74
+KPX T period -92
+KPX T o -74
+KPX T i -18
+KPX T hyphen -55
+KPX T e -74
+KPX T comma -92
+KPX T colon -74
+KPX T c -74
+KPX T a -74
+KPX T A -55
+
+KPX V u -18
+KPX V semicolon -18
+KPX V r -18
+KPX V period -92
+KPX V o -18
+KPX V hyphen -18
+KPX V e -18
+KPX V comma -92
+KPX V colon -18
+KPX V a -18
+KPX V A -37
+
+KPX W period -74
+KPX W o -18
+KPX W hyphen -18
+KPX W e -18
+KPX W comma -74
+KPX W a -18
+KPX W A -18
+
+KPX Y v -18
+KPX Y u -37
+KPX Y semicolon -37
+KPX Y q -55
+KPX Y period -111
+KPX Y p -37
+KPX Y o -55
+KPX Y i -18
+KPX Y hyphen -74
+KPX Y e -55
+KPX Y comma -111
+KPX Y colon -37
+KPX Y a -55
+KPX Y A -55
+
+KPX f quoteright 18
+
+KPX quoteleft quoteleft -18
+
+KPX quoteright s -55
+KPX quoteright quoteright -18
+
+KPX r z 20
+KPX r y 18
+KPX r x 20
+KPX r w 18
+KPX r v 18
+KPX r period -74
+KPX r hyphen -37
+KPX r f 20
+KPX r comma -74
+KPX r c -20
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -37
+KPX w comma -37
+
+KPX y period -55
+KPX y comma -55
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 112 194 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 112 194 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 112 194 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 112 194 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 153 194 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 112 194 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 84 194 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 84 194 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 84 194 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 84 194 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 194 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 194 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 194 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 194 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 139 194 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 139 194 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 139 194 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 139 194 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 139 194 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 139 194 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 194 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 139 194 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 139 194 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 139 194 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 139 194 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 112 194 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 112 194 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 84 194 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 56 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 56 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 56 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 56 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 82 30 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -55 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -55 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -55 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -55 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 56 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 84 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 56 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 28 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Narrow-Bold.afm b/tlt3.0/library/afm/Helvetica-Narrow-Bold.afm
new file mode 100644
index 0000000..3fdd6ef
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Narrow-Bold.afm
@@ -0,0 +1,571 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu Mar 15 11:47:27 1990
+Comment UniqueID 28398
+Comment VMusage 7614 43068
+FontName Helvetica-Narrow-Bold
+FullName Helvetica Narrow Bold
+FamilyName Helvetica
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -139 -228 822 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 228 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 273 ; N exclam ; B 74 0 200 718 ;
+C 34 ; WX 389 ; N quotedbl ; B 80 447 308 718 ;
+C 35 ; WX 456 ; N numbersign ; B 15 0 441 698 ;
+C 36 ; WX 456 ; N dollar ; B 25 -115 429 775 ;
+C 37 ; WX 729 ; N percent ; B 23 -19 706 710 ;
+C 38 ; WX 592 ; N ampersand ; B 44 -19 575 718 ;
+C 39 ; WX 228 ; N quoteright ; B 57 445 171 718 ;
+C 40 ; WX 273 ; N parenleft ; B 29 -208 257 734 ;
+C 41 ; WX 273 ; N parenright ; B 16 -208 244 734 ;
+C 42 ; WX 319 ; N asterisk ; B 22 387 297 718 ;
+C 43 ; WX 479 ; N plus ; B 33 0 446 506 ;
+C 44 ; WX 228 ; N comma ; B 52 -168 175 146 ;
+C 45 ; WX 273 ; N hyphen ; B 22 215 251 345 ;
+C 46 ; WX 228 ; N period ; B 52 0 175 146 ;
+C 47 ; WX 228 ; N slash ; B -27 -19 255 737 ;
+C 48 ; WX 456 ; N zero ; B 26 -19 430 710 ;
+C 49 ; WX 456 ; N one ; B 57 0 310 710 ;
+C 50 ; WX 456 ; N two ; B 21 0 419 710 ;
+C 51 ; WX 456 ; N three ; B 22 -19 423 710 ;
+C 52 ; WX 456 ; N four ; B 22 0 431 710 ;
+C 53 ; WX 456 ; N five ; B 22 -19 423 698 ;
+C 54 ; WX 456 ; N six ; B 25 -19 426 710 ;
+C 55 ; WX 456 ; N seven ; B 20 0 433 698 ;
+C 56 ; WX 456 ; N eight ; B 26 -19 430 710 ;
+C 57 ; WX 456 ; N nine ; B 25 -19 428 710 ;
+C 58 ; WX 273 ; N colon ; B 75 0 198 512 ;
+C 59 ; WX 273 ; N semicolon ; B 75 -168 198 512 ;
+C 60 ; WX 479 ; N less ; B 31 -8 448 514 ;
+C 61 ; WX 479 ; N equal ; B 33 87 446 419 ;
+C 62 ; WX 479 ; N greater ; B 31 -8 448 514 ;
+C 63 ; WX 501 ; N question ; B 49 0 456 727 ;
+C 64 ; WX 800 ; N at ; B 97 -19 702 737 ;
+C 65 ; WX 592 ; N A ; B 16 0 576 718 ;
+C 66 ; WX 592 ; N B ; B 62 0 549 718 ;
+C 67 ; WX 592 ; N C ; B 36 -19 561 737 ;
+C 68 ; WX 592 ; N D ; B 62 0 562 718 ;
+C 69 ; WX 547 ; N E ; B 62 0 509 718 ;
+C 70 ; WX 501 ; N F ; B 62 0 481 718 ;
+C 71 ; WX 638 ; N G ; B 36 -19 585 737 ;
+C 72 ; WX 592 ; N H ; B 58 0 534 718 ;
+C 73 ; WX 228 ; N I ; B 52 0 175 718 ;
+C 74 ; WX 456 ; N J ; B 18 -18 397 718 ;
+C 75 ; WX 592 ; N K ; B 71 0 592 718 ;
+C 76 ; WX 501 ; N L ; B 62 0 478 718 ;
+C 77 ; WX 683 ; N M ; B 57 0 627 718 ;
+C 78 ; WX 592 ; N N ; B 57 0 536 718 ;
+C 79 ; WX 638 ; N O ; B 36 -19 602 737 ;
+C 80 ; WX 547 ; N P ; B 62 0 514 718 ;
+C 81 ; WX 638 ; N Q ; B 36 -52 604 737 ;
+C 82 ; WX 592 ; N R ; B 62 0 555 718 ;
+C 83 ; WX 547 ; N S ; B 32 -19 516 737 ;
+C 84 ; WX 501 ; N T ; B 11 0 490 718 ;
+C 85 ; WX 592 ; N U ; B 59 -19 534 718 ;
+C 86 ; WX 547 ; N V ; B 16 0 531 718 ;
+C 87 ; WX 774 ; N W ; B 13 0 762 718 ;
+C 88 ; WX 547 ; N X ; B 11 0 535 718 ;
+C 89 ; WX 547 ; N Y ; B 12 0 535 718 ;
+C 90 ; WX 501 ; N Z ; B 20 0 481 718 ;
+C 91 ; WX 273 ; N bracketleft ; B 52 -196 253 722 ;
+C 92 ; WX 228 ; N backslash ; B -27 -19 255 737 ;
+C 93 ; WX 273 ; N bracketright ; B 20 -196 221 722 ;
+C 94 ; WX 479 ; N asciicircum ; B 51 323 428 698 ;
+C 95 ; WX 456 ; N underscore ; B 0 -125 456 -75 ;
+C 96 ; WX 228 ; N quoteleft ; B 57 454 171 727 ;
+C 97 ; WX 456 ; N a ; B 24 -14 432 546 ;
+C 98 ; WX 501 ; N b ; B 50 -14 474 718 ;
+C 99 ; WX 456 ; N c ; B 28 -14 430 546 ;
+C 100 ; WX 501 ; N d ; B 28 -14 452 718 ;
+C 101 ; WX 456 ; N e ; B 19 -14 433 546 ;
+C 102 ; WX 273 ; N f ; B 8 0 261 727 ; L i fi ; L l fl ;
+C 103 ; WX 501 ; N g ; B 33 -217 453 546 ;
+C 104 ; WX 501 ; N h ; B 53 0 448 718 ;
+C 105 ; WX 228 ; N i ; B 57 0 171 725 ;
+C 106 ; WX 228 ; N j ; B 2 -214 171 725 ;
+C 107 ; WX 456 ; N k ; B 57 0 461 718 ;
+C 108 ; WX 228 ; N l ; B 57 0 171 718 ;
+C 109 ; WX 729 ; N m ; B 52 0 677 546 ;
+C 110 ; WX 501 ; N n ; B 53 0 448 546 ;
+C 111 ; WX 501 ; N o ; B 28 -14 474 546 ;
+C 112 ; WX 501 ; N p ; B 51 -207 474 546 ;
+C 113 ; WX 501 ; N q ; B 28 -207 453 546 ;
+C 114 ; WX 319 ; N r ; B 52 0 306 546 ;
+C 115 ; WX 456 ; N s ; B 25 -14 426 546 ;
+C 116 ; WX 273 ; N t ; B 8 -6 253 676 ;
+C 117 ; WX 501 ; N u ; B 54 -14 447 532 ;
+C 118 ; WX 456 ; N v ; B 11 0 445 532 ;
+C 119 ; WX 638 ; N w ; B 8 0 631 532 ;
+C 120 ; WX 456 ; N x ; B 12 0 444 532 ;
+C 121 ; WX 456 ; N y ; B 8 -214 442 532 ;
+C 122 ; WX 410 ; N z ; B 16 0 394 532 ;
+C 123 ; WX 319 ; N braceleft ; B 39 -196 299 722 ;
+C 124 ; WX 230 ; N bar ; B 69 -19 161 737 ;
+C 125 ; WX 319 ; N braceright ; B 20 -196 280 722 ;
+C 126 ; WX 479 ; N asciitilde ; B 50 163 429 343 ;
+C 161 ; WX 273 ; N exclamdown ; B 74 -186 200 532 ;
+C 162 ; WX 456 ; N cent ; B 28 -118 430 628 ;
+C 163 ; WX 456 ; N sterling ; B 23 -16 444 718 ;
+C 164 ; WX 137 ; N fraction ; B -139 -19 276 710 ;
+C 165 ; WX 456 ; N yen ; B -7 0 463 698 ;
+C 166 ; WX 456 ; N florin ; B -8 -210 423 737 ;
+C 167 ; WX 456 ; N section ; B 28 -184 428 727 ;
+C 168 ; WX 456 ; N currency ; B -2 76 458 636 ;
+C 169 ; WX 195 ; N quotesingle ; B 57 447 138 718 ;
+C 170 ; WX 410 ; N quotedblleft ; B 52 454 358 727 ;
+C 171 ; WX 456 ; N guillemotleft ; B 72 76 384 484 ;
+C 172 ; WX 273 ; N guilsinglleft ; B 68 76 205 484 ;
+C 173 ; WX 273 ; N guilsinglright ; B 68 76 205 484 ;
+C 174 ; WX 501 ; N fi ; B 8 0 444 727 ;
+C 175 ; WX 501 ; N fl ; B 8 0 444 727 ;
+C 177 ; WX 456 ; N endash ; B 0 227 456 333 ;
+C 178 ; WX 456 ; N dagger ; B 30 -171 426 718 ;
+C 179 ; WX 456 ; N daggerdbl ; B 30 -171 426 718 ;
+C 180 ; WX 228 ; N periodcentered ; B 48 172 180 334 ;
+C 182 ; WX 456 ; N paragraph ; B -7 -191 442 700 ;
+C 183 ; WX 287 ; N bullet ; B 8 194 279 524 ;
+C 184 ; WX 228 ; N quotesinglbase ; B 57 -146 171 127 ;
+C 185 ; WX 410 ; N quotedblbase ; B 52 -146 358 127 ;
+C 186 ; WX 410 ; N quotedblright ; B 52 445 358 718 ;
+C 187 ; WX 456 ; N guillemotright ; B 72 76 384 484 ;
+C 188 ; WX 820 ; N ellipsis ; B 75 0 745 146 ;
+C 189 ; WX 820 ; N perthousand ; B -2 -19 822 710 ;
+C 191 ; WX 501 ; N questiondown ; B 45 -195 452 532 ;
+C 193 ; WX 273 ; N grave ; B -19 604 184 750 ;
+C 194 ; WX 273 ; N acute ; B 89 604 292 750 ;
+C 195 ; WX 273 ; N circumflex ; B -8 604 281 750 ;
+C 196 ; WX 273 ; N tilde ; B -14 610 287 737 ;
+C 197 ; WX 273 ; N macron ; B -5 604 278 678 ;
+C 198 ; WX 273 ; N breve ; B -2 604 275 750 ;
+C 199 ; WX 273 ; N dotaccent ; B 85 614 189 729 ;
+C 200 ; WX 273 ; N dieresis ; B 5 614 268 729 ;
+C 202 ; WX 273 ; N ring ; B 48 568 225 776 ;
+C 203 ; WX 273 ; N cedilla ; B 5 -228 201 0 ;
+C 205 ; WX 273 ; N hungarumlaut ; B 7 604 399 750 ;
+C 206 ; WX 273 ; N ogonek ; B 58 -228 249 0 ;
+C 207 ; WX 273 ; N caron ; B -8 604 281 750 ;
+C 208 ; WX 820 ; N emdash ; B 0 227 820 333 ;
+C 225 ; WX 820 ; N AE ; B 4 0 782 718 ;
+C 227 ; WX 303 ; N ordfeminine ; B 18 276 285 737 ;
+C 232 ; WX 501 ; N Lslash ; B -16 0 478 718 ;
+C 233 ; WX 638 ; N Oslash ; B 27 -27 610 745 ;
+C 234 ; WX 820 ; N OE ; B 30 -19 788 737 ;
+C 235 ; WX 299 ; N ordmasculine ; B 5 276 295 737 ;
+C 241 ; WX 729 ; N ae ; B 24 -14 704 546 ;
+C 245 ; WX 228 ; N dotlessi ; B 57 0 171 532 ;
+C 248 ; WX 228 ; N lslash ; B -15 0 243 718 ;
+C 249 ; WX 501 ; N oslash ; B 18 -29 483 560 ;
+C 250 ; WX 774 ; N oe ; B 28 -14 748 546 ;
+C 251 ; WX 501 ; N germandbls ; B 57 -14 475 731 ;
+C -1 ; WX 501 ; N Zcaron ; B 20 0 481 936 ;
+C -1 ; WX 456 ; N ccedilla ; B 28 -228 430 546 ;
+C -1 ; WX 456 ; N ydieresis ; B 8 -214 442 729 ;
+C -1 ; WX 456 ; N atilde ; B 24 -14 432 737 ;
+C -1 ; WX 228 ; N icircumflex ; B -30 0 259 750 ;
+C -1 ; WX 273 ; N threesuperior ; B 7 271 267 710 ;
+C -1 ; WX 456 ; N ecircumflex ; B 19 -14 433 750 ;
+C -1 ; WX 501 ; N thorn ; B 51 -208 474 718 ;
+C -1 ; WX 456 ; N egrave ; B 19 -14 433 750 ;
+C -1 ; WX 273 ; N twosuperior ; B 7 283 266 710 ;
+C -1 ; WX 456 ; N eacute ; B 19 -14 433 750 ;
+C -1 ; WX 501 ; N otilde ; B 28 -14 474 737 ;
+C -1 ; WX 592 ; N Aacute ; B 16 0 576 936 ;
+C -1 ; WX 501 ; N ocircumflex ; B 28 -14 474 750 ;
+C -1 ; WX 456 ; N yacute ; B 8 -214 442 750 ;
+C -1 ; WX 501 ; N udieresis ; B 54 -14 447 729 ;
+C -1 ; WX 684 ; N threequarters ; B 13 -19 655 710 ;
+C -1 ; WX 456 ; N acircumflex ; B 24 -14 432 750 ;
+C -1 ; WX 592 ; N Eth ; B -4 0 562 718 ;
+C -1 ; WX 456 ; N edieresis ; B 19 -14 433 729 ;
+C -1 ; WX 501 ; N ugrave ; B 54 -14 447 750 ;
+C -1 ; WX 820 ; N trademark ; B 36 306 784 718 ;
+C -1 ; WX 501 ; N ograve ; B 28 -14 474 750 ;
+C -1 ; WX 456 ; N scaron ; B 25 -14 426 750 ;
+C -1 ; WX 228 ; N Idieresis ; B -17 0 246 915 ;
+C -1 ; WX 501 ; N uacute ; B 54 -14 447 750 ;
+C -1 ; WX 456 ; N agrave ; B 24 -14 432 750 ;
+C -1 ; WX 501 ; N ntilde ; B 53 0 448 737 ;
+C -1 ; WX 456 ; N aring ; B 24 -14 432 776 ;
+C -1 ; WX 410 ; N zcaron ; B 16 0 394 750 ;
+C -1 ; WX 228 ; N Icircumflex ; B -30 0 259 936 ;
+C -1 ; WX 592 ; N Ntilde ; B 57 0 536 923 ;
+C -1 ; WX 501 ; N ucircumflex ; B 54 -14 447 750 ;
+C -1 ; WX 547 ; N Ecircumflex ; B 62 0 509 936 ;
+C -1 ; WX 228 ; N Iacute ; B 52 0 270 936 ;
+C -1 ; WX 592 ; N Ccedilla ; B 36 -228 561 737 ;
+C -1 ; WX 638 ; N Odieresis ; B 36 -19 602 915 ;
+C -1 ; WX 547 ; N Scaron ; B 32 -19 516 936 ;
+C -1 ; WX 547 ; N Edieresis ; B 62 0 509 915 ;
+C -1 ; WX 228 ; N Igrave ; B -41 0 175 936 ;
+C -1 ; WX 456 ; N adieresis ; B 24 -14 432 729 ;
+C -1 ; WX 638 ; N Ograve ; B 36 -19 602 936 ;
+C -1 ; WX 547 ; N Egrave ; B 62 0 509 936 ;
+C -1 ; WX 547 ; N Ydieresis ; B 12 0 535 915 ;
+C -1 ; WX 604 ; N registered ; B -9 -19 613 737 ;
+C -1 ; WX 638 ; N Otilde ; B 36 -19 602 923 ;
+C -1 ; WX 684 ; N onequarter ; B 21 -19 628 710 ;
+C -1 ; WX 592 ; N Ugrave ; B 59 -19 534 936 ;
+C -1 ; WX 592 ; N Ucircumflex ; B 59 -19 534 936 ;
+C -1 ; WX 547 ; N Thorn ; B 62 0 514 718 ;
+C -1 ; WX 479 ; N divide ; B 33 -42 446 548 ;
+C -1 ; WX 592 ; N Atilde ; B 16 0 576 923 ;
+C -1 ; WX 592 ; N Uacute ; B 59 -19 534 936 ;
+C -1 ; WX 638 ; N Ocircumflex ; B 36 -19 602 936 ;
+C -1 ; WX 479 ; N logicalnot ; B 33 108 446 419 ;
+C -1 ; WX 592 ; N Aring ; B 16 0 576 962 ;
+C -1 ; WX 228 ; N idieresis ; B -17 0 246 729 ;
+C -1 ; WX 228 ; N iacute ; B 57 0 270 750 ;
+C -1 ; WX 456 ; N aacute ; B 24 -14 432 750 ;
+C -1 ; WX 479 ; N plusminus ; B 33 0 446 506 ;
+C -1 ; WX 479 ; N multiply ; B 33 1 447 505 ;
+C -1 ; WX 592 ; N Udieresis ; B 59 -19 534 915 ;
+C -1 ; WX 479 ; N minus ; B 33 197 446 309 ;
+C -1 ; WX 273 ; N onesuperior ; B 21 283 194 710 ;
+C -1 ; WX 547 ; N Eacute ; B 62 0 509 936 ;
+C -1 ; WX 592 ; N Acircumflex ; B 16 0 576 936 ;
+C -1 ; WX 604 ; N copyright ; B -9 -19 614 737 ;
+C -1 ; WX 592 ; N Agrave ; B 16 0 576 936 ;
+C -1 ; WX 501 ; N odieresis ; B 28 -14 474 729 ;
+C -1 ; WX 501 ; N oacute ; B 28 -14 474 750 ;
+C -1 ; WX 328 ; N degree ; B 47 426 281 712 ;
+C -1 ; WX 228 ; N igrave ; B -41 0 171 750 ;
+C -1 ; WX 501 ; N mu ; B 54 -207 447 532 ;
+C -1 ; WX 638 ; N Oacute ; B 36 -19 602 936 ;
+C -1 ; WX 501 ; N eth ; B 28 -14 474 737 ;
+C -1 ; WX 592 ; N Adieresis ; B 16 0 576 915 ;
+C -1 ; WX 547 ; N Yacute ; B 12 0 535 936 ;
+C -1 ; WX 230 ; N brokenbar ; B 69 -19 161 737 ;
+C -1 ; WX 684 ; N onehalf ; B 21 -19 651 710 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 209
+
+KPX A y -24
+KPX A w -24
+KPX A v -32
+KPX A u -24
+KPX A Y -89
+KPX A W -48
+KPX A V -65
+KPX A U -40
+KPX A T -73
+KPX A Q -32
+KPX A O -32
+KPX A G -40
+KPX A C -32
+
+KPX B U -7
+KPX B A -24
+
+KPX D period -24
+KPX D comma -24
+KPX D Y -56
+KPX D W -32
+KPX D V -32
+KPX D A -32
+
+KPX F period -81
+KPX F comma -81
+KPX F a -15
+KPX F A -65
+
+KPX J u -15
+KPX J period -15
+KPX J comma -15
+KPX J A -15
+
+KPX K y -32
+KPX K u -24
+KPX K o -28
+KPX K e -11
+KPX K O -24
+
+KPX L y -24
+KPX L quoteright -114
+KPX L quotedblright -114
+KPX L Y -97
+KPX L W -65
+KPX L V -89
+KPX L T -73
+
+KPX O period -32
+KPX O comma -32
+KPX O Y -56
+KPX O X -40
+KPX O W -40
+KPX O V -40
+KPX O T -32
+KPX O A -40
+
+KPX P period -97
+KPX P o -32
+KPX P e -24
+KPX P comma -97
+KPX P a -24
+KPX P A -81
+
+KPX Q period 16
+KPX Q comma 16
+KPX Q U -7
+
+KPX R Y -40
+KPX R W -32
+KPX R V -40
+KPX R U -15
+KPX R T -15
+KPX R O -15
+
+KPX T y -48
+KPX T w -48
+KPX T u -73
+KPX T semicolon -32
+KPX T r -65
+KPX T period -65
+KPX T o -65
+KPX T hyphen -97
+KPX T e -48
+KPX T comma -65
+KPX T colon -32
+KPX T a -65
+KPX T O -32
+KPX T A -73
+
+KPX U period -24
+KPX U comma -24
+KPX U A -40
+
+KPX V u -48
+KPX V semicolon -32
+KPX V period -97
+KPX V o -73
+KPX V hyphen -65
+KPX V e -40
+KPX V comma -97
+KPX V colon -32
+KPX V a -48
+KPX V O -40
+KPX V G -40
+KPX V A -65
+
+KPX W y -15
+KPX W u -36
+KPX W semicolon -7
+KPX W period -65
+KPX W o -48
+KPX W hyphen -32
+KPX W e -28
+KPX W comma -65
+KPX W colon -7
+KPX W a -32
+KPX W O -15
+KPX W A -48
+
+KPX Y u -81
+KPX Y semicolon -40
+KPX Y period -81
+KPX Y o -81
+KPX Y e -65
+KPX Y comma -81
+KPX Y colon -40
+KPX Y a -73
+KPX Y O -56
+KPX Y A -89
+
+KPX a y -15
+KPX a w -11
+KPX a v -11
+KPX a g -7
+
+KPX b y -15
+KPX b v -15
+KPX b u -15
+KPX b l -7
+
+KPX c y -7
+KPX c l -15
+KPX c k -15
+KPX c h -7
+
+KPX colon space -32
+
+KPX comma space -32
+KPX comma quoteright -97
+KPX comma quotedblright -97
+
+KPX d y -11
+KPX d w -11
+KPX d v -11
+KPX d d -7
+
+KPX e y -11
+KPX e x -11
+KPX e w -11
+KPX e v -11
+KPX e period 16
+KPX e comma 8
+
+KPX f quoteright 25
+KPX f quotedblright 25
+KPX f period -7
+KPX f o -15
+KPX f e -7
+KPX f comma -7
+
+KPX g g -7
+KPX g e 8
+
+KPX h y -15
+
+KPX k o -11
+
+KPX l y -11
+KPX l w -11
+
+KPX m y -24
+KPX m u -15
+
+KPX n y -15
+KPX n v -32
+KPX n u -7
+
+KPX o y -15
+KPX o x -24
+KPX o w -11
+KPX o v -15
+
+KPX p y -11
+
+KPX period space -32
+KPX period quoteright -97
+KPX period quotedblright -97
+
+KPX quotedblright space -65
+
+KPX quoteleft quoteleft -37
+
+KPX quoteright v -15
+KPX quoteright space -65
+KPX quoteright s -48
+KPX quoteright r -32
+KPX quoteright quoteright -37
+KPX quoteright l -15
+KPX quoteright d -65
+
+KPX r y 8
+KPX r v 8
+KPX r t 16
+KPX r s -11
+KPX r q -15
+KPX r period -48
+KPX r o -15
+KPX r hyphen -15
+KPX r g -11
+KPX r d -15
+KPX r comma -48
+KPX r c -15
+
+KPX s w -11
+
+KPX semicolon space -32
+
+KPX space quoteleft -48
+KPX space quotedblleft -65
+KPX space Y -97
+KPX space W -65
+KPX space V -65
+KPX space T -81
+
+KPX v period -65
+KPX v o -24
+KPX v comma -65
+KPX v a -15
+
+KPX w period -32
+KPX w o -15
+KPX w comma -32
+
+KPX x e -7
+
+KPX y period -65
+KPX y o -20
+KPX y e -7
+KPX y comma -65
+KPX y a -24
+
+KPX z e 8
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 160 186 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 160 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 160 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 160 186 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 160 186 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 176 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 137 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 137 186 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 137 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 137 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -22 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -22 186 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -22 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -22 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 160 186 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 183 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 183 186 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 183 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 183 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 183 186 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 137 186 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 160 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 160 186 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 160 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 160 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 137 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 137 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 114 186 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 92 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 92 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 92 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 92 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 92 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 92 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 108 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 92 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 92 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 92 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 92 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -22 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -22 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -22 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -22 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 114 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 114 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 114 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 114 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 114 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 114 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 92 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 114 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 114 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 114 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 114 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 92 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 92 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 69 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Narrow-BoldOblique.afm b/tlt3.0/library/afm/Helvetica-Narrow-BoldOblique.afm
new file mode 100644
index 0000000..ff859b3
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Narrow-BoldOblique.afm
@@ -0,0 +1,571 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Thu Mar 15 12:08:57 1990
+Comment UniqueID 28407
+Comment VMusage 7614 43068
+FontName Helvetica-Narrow-BoldOblique
+FullName Helvetica Narrow Bold Oblique
+FamilyName Helvetica
+Weight Bold
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -143 -228 913 962
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 532
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 228 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 273 ; N exclam ; B 77 0 325 718 ;
+C 34 ; WX 389 ; N quotedbl ; B 158 447 433 718 ;
+C 35 ; WX 456 ; N numbersign ; B 49 0 528 698 ;
+C 36 ; WX 456 ; N dollar ; B 55 -115 510 775 ;
+C 37 ; WX 729 ; N percent ; B 112 -19 739 710 ;
+C 38 ; WX 592 ; N ampersand ; B 73 -19 600 718 ;
+C 39 ; WX 228 ; N quoteright ; B 137 445 297 718 ;
+C 40 ; WX 273 ; N parenleft ; B 62 -208 385 734 ;
+C 41 ; WX 273 ; N parenright ; B -21 -208 302 734 ;
+C 42 ; WX 319 ; N asterisk ; B 120 387 394 718 ;
+C 43 ; WX 479 ; N plus ; B 67 0 500 506 ;
+C 44 ; WX 228 ; N comma ; B 23 -168 201 146 ;
+C 45 ; WX 273 ; N hyphen ; B 60 215 311 345 ;
+C 46 ; WX 228 ; N period ; B 52 0 201 146 ;
+C 47 ; WX 228 ; N slash ; B -30 -19 383 737 ;
+C 48 ; WX 456 ; N zero ; B 71 -19 506 710 ;
+C 49 ; WX 456 ; N one ; B 142 0 434 710 ;
+C 50 ; WX 456 ; N two ; B 21 0 508 710 ;
+C 51 ; WX 456 ; N three ; B 54 -19 499 710 ;
+C 52 ; WX 456 ; N four ; B 50 0 490 710 ;
+C 53 ; WX 456 ; N five ; B 53 -19 522 698 ;
+C 54 ; WX 456 ; N six ; B 70 -19 507 710 ;
+C 55 ; WX 456 ; N seven ; B 102 0 555 698 ;
+C 56 ; WX 456 ; N eight ; B 57 -19 505 710 ;
+C 57 ; WX 456 ; N nine ; B 64 -19 504 710 ;
+C 58 ; WX 273 ; N colon ; B 75 0 288 512 ;
+C 59 ; WX 273 ; N semicolon ; B 46 -168 288 512 ;
+C 60 ; WX 479 ; N less ; B 67 -8 537 514 ;
+C 61 ; WX 479 ; N equal ; B 48 87 519 419 ;
+C 62 ; WX 479 ; N greater ; B 30 -8 500 514 ;
+C 63 ; WX 501 ; N question ; B 135 0 550 727 ;
+C 64 ; WX 800 ; N at ; B 152 -19 782 737 ;
+C 65 ; WX 592 ; N A ; B 16 0 576 718 ;
+C 66 ; WX 592 ; N B ; B 62 0 626 718 ;
+C 67 ; WX 592 ; N C ; B 88 -19 647 737 ;
+C 68 ; WX 592 ; N D ; B 62 0 637 718 ;
+C 69 ; WX 547 ; N E ; B 62 0 620 718 ;
+C 70 ; WX 501 ; N F ; B 62 0 606 718 ;
+C 71 ; WX 638 ; N G ; B 89 -19 670 737 ;
+C 72 ; WX 592 ; N H ; B 58 0 659 718 ;
+C 73 ; WX 228 ; N I ; B 52 0 301 718 ;
+C 74 ; WX 456 ; N J ; B 49 -18 522 718 ;
+C 75 ; WX 592 ; N K ; B 71 0 703 718 ;
+C 76 ; WX 501 ; N L ; B 62 0 501 718 ;
+C 77 ; WX 683 ; N M ; B 57 0 752 718 ;
+C 78 ; WX 592 ; N N ; B 57 0 661 718 ;
+C 79 ; WX 638 ; N O ; B 88 -19 675 737 ;
+C 80 ; WX 547 ; N P ; B 62 0 605 718 ;
+C 81 ; WX 638 ; N Q ; B 88 -52 675 737 ;
+C 82 ; WX 592 ; N R ; B 62 0 638 718 ;
+C 83 ; WX 547 ; N S ; B 66 -19 588 737 ;
+C 84 ; WX 501 ; N T ; B 114 0 615 718 ;
+C 85 ; WX 592 ; N U ; B 96 -19 659 718 ;
+C 86 ; WX 547 ; N V ; B 141 0 656 718 ;
+C 87 ; WX 774 ; N W ; B 138 0 887 718 ;
+C 88 ; WX 547 ; N X ; B 11 0 648 718 ;
+C 89 ; WX 547 ; N Y ; B 137 0 661 718 ;
+C 90 ; WX 501 ; N Z ; B 20 0 604 718 ;
+C 91 ; WX 273 ; N bracketleft ; B 17 -196 379 722 ;
+C 92 ; WX 228 ; N backslash ; B 101 -19 252 737 ;
+C 93 ; WX 273 ; N bracketright ; B -14 -196 347 722 ;
+C 94 ; WX 479 ; N asciicircum ; B 107 323 484 698 ;
+C 95 ; WX 456 ; N underscore ; B -22 -125 443 -75 ;
+C 96 ; WX 228 ; N quoteleft ; B 136 454 296 727 ;
+C 97 ; WX 456 ; N a ; B 45 -14 478 546 ;
+C 98 ; WX 501 ; N b ; B 50 -14 529 718 ;
+C 99 ; WX 456 ; N c ; B 65 -14 491 546 ;
+C 100 ; WX 501 ; N d ; B 67 -14 577 718 ;
+C 101 ; WX 456 ; N e ; B 58 -14 486 546 ;
+C 102 ; WX 273 ; N f ; B 71 0 385 727 ; L i fi ; L l fl ;
+C 103 ; WX 501 ; N g ; B 31 -217 546 546 ;
+C 104 ; WX 501 ; N h ; B 53 0 516 718 ;
+C 105 ; WX 228 ; N i ; B 57 0 298 725 ;
+C 106 ; WX 228 ; N j ; B -35 -214 298 725 ;
+C 107 ; WX 456 ; N k ; B 57 0 549 718 ;
+C 108 ; WX 228 ; N l ; B 57 0 297 718 ;
+C 109 ; WX 729 ; N m ; B 52 0 746 546 ;
+C 110 ; WX 501 ; N n ; B 53 0 516 546 ;
+C 111 ; WX 501 ; N o ; B 67 -14 527 546 ;
+C 112 ; WX 501 ; N p ; B 15 -207 529 546 ;
+C 113 ; WX 501 ; N q ; B 66 -207 545 546 ;
+C 114 ; WX 319 ; N r ; B 52 0 401 546 ;
+C 115 ; WX 456 ; N s ; B 52 -14 479 546 ;
+C 116 ; WX 273 ; N t ; B 82 -6 346 676 ;
+C 117 ; WX 501 ; N u ; B 80 -14 540 532 ;
+C 118 ; WX 456 ; N v ; B 103 0 538 532 ;
+C 119 ; WX 638 ; N w ; B 101 0 723 532 ;
+C 120 ; WX 456 ; N x ; B 12 0 531 532 ;
+C 121 ; WX 456 ; N y ; B 34 -214 535 532 ;
+C 122 ; WX 410 ; N z ; B 16 0 478 532 ;
+C 123 ; WX 319 ; N braceleft ; B 77 -196 425 722 ;
+C 124 ; WX 230 ; N bar ; B 66 -19 289 737 ;
+C 125 ; WX 319 ; N braceright ; B -14 -196 333 722 ;
+C 126 ; WX 479 ; N asciitilde ; B 94 163 473 343 ;
+C 161 ; WX 273 ; N exclamdown ; B 41 -186 290 532 ;
+C 162 ; WX 456 ; N cent ; B 65 -118 491 628 ;
+C 163 ; WX 456 ; N sterling ; B 41 -16 520 718 ;
+C 164 ; WX 137 ; N fraction ; B -143 -19 399 710 ;
+C 165 ; WX 456 ; N yen ; B 49 0 585 698 ;
+C 166 ; WX 456 ; N florin ; B -41 -210 548 737 ;
+C 167 ; WX 456 ; N section ; B 50 -184 491 727 ;
+C 168 ; WX 456 ; N currency ; B 22 76 558 636 ;
+C 169 ; WX 195 ; N quotesingle ; B 135 447 263 718 ;
+C 170 ; WX 410 ; N quotedblleft ; B 132 454 482 727 ;
+C 171 ; WX 456 ; N guillemotleft ; B 111 76 468 484 ;
+C 172 ; WX 273 ; N guilsinglleft ; B 106 76 289 484 ;
+C 173 ; WX 273 ; N guilsinglright ; B 81 76 264 484 ;
+C 174 ; WX 501 ; N fi ; B 71 0 571 727 ;
+C 175 ; WX 501 ; N fl ; B 71 0 570 727 ;
+C 177 ; WX 456 ; N endash ; B 40 227 514 333 ;
+C 178 ; WX 456 ; N dagger ; B 97 -171 513 718 ;
+C 179 ; WX 456 ; N daggerdbl ; B 38 -171 515 718 ;
+C 180 ; WX 228 ; N periodcentered ; B 90 172 226 334 ;
+C 182 ; WX 456 ; N paragraph ; B 80 -191 564 700 ;
+C 183 ; WX 287 ; N bullet ; B 68 194 345 524 ;
+C 184 ; WX 228 ; N quotesinglbase ; B 34 -146 194 127 ;
+C 185 ; WX 410 ; N quotedblbase ; B 29 -146 380 127 ;
+C 186 ; WX 410 ; N quotedblright ; B 132 445 483 718 ;
+C 187 ; WX 456 ; N guillemotright ; B 85 76 443 484 ;
+C 188 ; WX 820 ; N ellipsis ; B 75 0 770 146 ;
+C 189 ; WX 820 ; N perthousand ; B 62 -19 851 710 ;
+C 191 ; WX 501 ; N questiondown ; B 44 -195 459 532 ;
+C 193 ; WX 273 ; N grave ; B 112 604 290 750 ;
+C 194 ; WX 273 ; N acute ; B 194 604 423 750 ;
+C 195 ; WX 273 ; N circumflex ; B 97 604 387 750 ;
+C 196 ; WX 273 ; N tilde ; B 92 610 415 737 ;
+C 197 ; WX 273 ; N macron ; B 100 604 396 678 ;
+C 198 ; WX 273 ; N breve ; B 128 604 405 750 ;
+C 199 ; WX 273 ; N dotaccent ; B 192 614 316 729 ;
+C 200 ; WX 273 ; N dieresis ; B 112 614 395 729 ;
+C 202 ; WX 273 ; N ring ; B 164 568 344 776 ;
+C 203 ; WX 273 ; N cedilla ; B -30 -228 180 0 ;
+C 205 ; WX 273 ; N hungarumlaut ; B 113 604 529 750 ;
+C 206 ; WX 273 ; N ogonek ; B 33 -228 216 0 ;
+C 207 ; WX 273 ; N caron ; B 123 604 412 750 ;
+C 208 ; WX 820 ; N emdash ; B 40 227 878 333 ;
+C 225 ; WX 820 ; N AE ; B 4 0 902 718 ;
+C 227 ; WX 303 ; N ordfeminine ; B 75 276 381 737 ;
+C 232 ; WX 501 ; N Lslash ; B 28 0 501 718 ;
+C 233 ; WX 638 ; N Oslash ; B 29 -27 733 745 ;
+C 234 ; WX 820 ; N OE ; B 81 -19 913 737 ;
+C 235 ; WX 299 ; N ordmasculine ; B 75 276 398 737 ;
+C 241 ; WX 729 ; N ae ; B 46 -14 757 546 ;
+C 245 ; WX 228 ; N dotlessi ; B 57 0 264 532 ;
+C 248 ; WX 228 ; N lslash ; B 33 0 334 718 ;
+C 249 ; WX 501 ; N oslash ; B 18 -29 575 560 ;
+C 250 ; WX 774 ; N oe ; B 67 -14 801 546 ;
+C 251 ; WX 501 ; N germandbls ; B 57 -14 539 731 ;
+C -1 ; WX 501 ; N Zcaron ; B 20 0 604 936 ;
+C -1 ; WX 456 ; N ccedilla ; B 65 -228 491 546 ;
+C -1 ; WX 456 ; N ydieresis ; B 34 -214 535 729 ;
+C -1 ; WX 456 ; N atilde ; B 45 -14 507 737 ;
+C -1 ; WX 228 ; N icircumflex ; B 57 0 364 750 ;
+C -1 ; WX 273 ; N threesuperior ; B 75 271 361 710 ;
+C -1 ; WX 456 ; N ecircumflex ; B 58 -14 486 750 ;
+C -1 ; WX 501 ; N thorn ; B 15 -208 529 718 ;
+C -1 ; WX 456 ; N egrave ; B 58 -14 486 750 ;
+C -1 ; WX 273 ; N twosuperior ; B 57 283 368 710 ;
+C -1 ; WX 456 ; N eacute ; B 58 -14 514 750 ;
+C -1 ; WX 501 ; N otilde ; B 67 -14 529 737 ;
+C -1 ; WX 592 ; N Aacute ; B 16 0 615 936 ;
+C -1 ; WX 501 ; N ocircumflex ; B 67 -14 527 750 ;
+C -1 ; WX 456 ; N yacute ; B 34 -214 535 750 ;
+C -1 ; WX 501 ; N udieresis ; B 80 -14 540 729 ;
+C -1 ; WX 684 ; N threequarters ; B 82 -19 688 710 ;
+C -1 ; WX 456 ; N acircumflex ; B 45 -14 478 750 ;
+C -1 ; WX 592 ; N Eth ; B 51 0 637 718 ;
+C -1 ; WX 456 ; N edieresis ; B 58 -14 487 729 ;
+C -1 ; WX 501 ; N ugrave ; B 80 -14 540 750 ;
+C -1 ; WX 820 ; N trademark ; B 146 306 909 718 ;
+C -1 ; WX 501 ; N ograve ; B 67 -14 527 750 ;
+C -1 ; WX 456 ; N scaron ; B 52 -14 504 750 ;
+C -1 ; WX 228 ; N Idieresis ; B 52 0 405 915 ;
+C -1 ; WX 501 ; N uacute ; B 80 -14 540 750 ;
+C -1 ; WX 456 ; N agrave ; B 45 -14 478 750 ;
+C -1 ; WX 501 ; N ntilde ; B 53 0 529 737 ;
+C -1 ; WX 456 ; N aring ; B 45 -14 478 776 ;
+C -1 ; WX 410 ; N zcaron ; B 16 0 481 750 ;
+C -1 ; WX 228 ; N Icircumflex ; B 52 0 397 936 ;
+C -1 ; WX 592 ; N Ntilde ; B 57 0 661 923 ;
+C -1 ; WX 501 ; N ucircumflex ; B 80 -14 540 750 ;
+C -1 ; WX 547 ; N Ecircumflex ; B 62 0 620 936 ;
+C -1 ; WX 228 ; N Iacute ; B 52 0 433 936 ;
+C -1 ; WX 592 ; N Ccedilla ; B 88 -228 647 737 ;
+C -1 ; WX 638 ; N Odieresis ; B 88 -19 675 915 ;
+C -1 ; WX 547 ; N Scaron ; B 66 -19 588 936 ;
+C -1 ; WX 547 ; N Edieresis ; B 62 0 620 915 ;
+C -1 ; WX 228 ; N Igrave ; B 52 0 301 936 ;
+C -1 ; WX 456 ; N adieresis ; B 45 -14 487 729 ;
+C -1 ; WX 638 ; N Ograve ; B 88 -19 675 936 ;
+C -1 ; WX 547 ; N Egrave ; B 62 0 620 936 ;
+C -1 ; WX 547 ; N Ydieresis ; B 137 0 661 915 ;
+C -1 ; WX 604 ; N registered ; B 45 -19 684 737 ;
+C -1 ; WX 638 ; N Otilde ; B 88 -19 675 923 ;
+C -1 ; WX 684 ; N onequarter ; B 108 -19 661 710 ;
+C -1 ; WX 592 ; N Ugrave ; B 96 -19 659 936 ;
+C -1 ; WX 592 ; N Ucircumflex ; B 96 -19 659 936 ;
+C -1 ; WX 547 ; N Thorn ; B 62 0 588 718 ;
+C -1 ; WX 479 ; N divide ; B 67 -42 500 548 ;
+C -1 ; WX 592 ; N Atilde ; B 16 0 608 923 ;
+C -1 ; WX 592 ; N Uacute ; B 96 -19 659 936 ;
+C -1 ; WX 638 ; N Ocircumflex ; B 88 -19 675 936 ;
+C -1 ; WX 479 ; N logicalnot ; B 86 108 519 419 ;
+C -1 ; WX 592 ; N Aring ; B 16 0 576 962 ;
+C -1 ; WX 228 ; N idieresis ; B 57 0 373 729 ;
+C -1 ; WX 228 ; N iacute ; B 57 0 400 750 ;
+C -1 ; WX 456 ; N aacute ; B 45 -14 514 750 ;
+C -1 ; WX 479 ; N plusminus ; B 33 0 512 506 ;
+C -1 ; WX 479 ; N multiply ; B 47 1 520 505 ;
+C -1 ; WX 592 ; N Udieresis ; B 96 -19 659 915 ;
+C -1 ; WX 479 ; N minus ; B 67 197 500 309 ;
+C -1 ; WX 273 ; N onesuperior ; B 121 283 318 710 ;
+C -1 ; WX 547 ; N Eacute ; B 62 0 620 936 ;
+C -1 ; WX 592 ; N Acircumflex ; B 16 0 579 936 ;
+C -1 ; WX 604 ; N copyright ; B 46 -19 685 737 ;
+C -1 ; WX 592 ; N Agrave ; B 16 0 576 936 ;
+C -1 ; WX 501 ; N odieresis ; B 67 -14 527 729 ;
+C -1 ; WX 501 ; N oacute ; B 67 -14 537 750 ;
+C -1 ; WX 328 ; N degree ; B 143 426 383 712 ;
+C -1 ; WX 228 ; N igrave ; B 57 0 268 750 ;
+C -1 ; WX 501 ; N mu ; B 18 -207 540 532 ;
+C -1 ; WX 638 ; N Oacute ; B 88 -19 675 936 ;
+C -1 ; WX 501 ; N eth ; B 67 -14 549 737 ;
+C -1 ; WX 592 ; N Adieresis ; B 16 0 588 915 ;
+C -1 ; WX 547 ; N Yacute ; B 137 0 661 936 ;
+C -1 ; WX 230 ; N brokenbar ; B 66 -19 289 737 ;
+C -1 ; WX 684 ; N onehalf ; B 108 -19 704 710 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 209
+
+KPX A y -30
+KPX A w -30
+KPX A v -40
+KPX A u -30
+KPX A Y -110
+KPX A W -60
+KPX A V -80
+KPX A U -50
+KPX A T -90
+KPX A Q -40
+KPX A O -40
+KPX A G -50
+KPX A C -40
+
+KPX B U -10
+KPX B A -30
+
+KPX D period -30
+KPX D comma -30
+KPX D Y -70
+KPX D W -40
+KPX D V -40
+KPX D A -40
+
+KPX F period -100
+KPX F comma -100
+KPX F a -20
+KPX F A -80
+
+KPX J u -20
+KPX J period -20
+KPX J comma -20
+KPX J A -20
+
+KPX K y -40
+KPX K u -30
+KPX K o -35
+KPX K e -15
+KPX K O -30
+
+KPX L y -30
+KPX L quoteright -140
+KPX L quotedblright -140
+KPX L Y -120
+KPX L W -80
+KPX L V -110
+KPX L T -90
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -50
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -50
+
+KPX P period -120
+KPX P o -40
+KPX P e -30
+KPX P comma -120
+KPX P a -30
+KPX P A -100
+
+KPX Q period 20
+KPX Q comma 20
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -40
+KPX R V -50
+KPX R U -20
+KPX R T -20
+KPX R O -20
+
+KPX T y -60
+KPX T w -60
+KPX T u -90
+KPX T semicolon -40
+KPX T r -80
+KPX T period -80
+KPX T o -80
+KPX T hyphen -120
+KPX T e -60
+KPX T comma -80
+KPX T colon -40
+KPX T a -80
+KPX T O -40
+KPX T A -90
+
+KPX U period -30
+KPX U comma -30
+KPX U A -50
+
+KPX V u -60
+KPX V semicolon -40
+KPX V period -120
+KPX V o -90
+KPX V hyphen -80
+KPX V e -50
+KPX V comma -120
+KPX V colon -40
+KPX V a -60
+KPX V O -50
+KPX V G -50
+KPX V A -80
+
+KPX W y -20
+KPX W u -45
+KPX W semicolon -10
+KPX W period -80
+KPX W o -60
+KPX W hyphen -40
+KPX W e -35
+KPX W comma -80
+KPX W colon -10
+KPX W a -40
+KPX W O -20
+KPX W A -60
+
+KPX Y u -100
+KPX Y semicolon -50
+KPX Y period -100
+KPX Y o -100
+KPX Y e -80
+KPX Y comma -100
+KPX Y colon -50
+KPX Y a -90
+KPX Y O -70
+KPX Y A -110
+
+KPX a y -20
+KPX a w -15
+KPX a v -15
+KPX a g -10
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b l -10
+
+KPX c y -10
+KPX c l -20
+KPX c k -20
+KPX c h -10
+
+KPX colon space -40
+
+KPX comma space -40
+KPX comma quoteright -120
+KPX comma quotedblright -120
+
+KPX d y -15
+KPX d w -15
+KPX d v -15
+KPX d d -10
+
+KPX e y -15
+KPX e x -15
+KPX e w -15
+KPX e v -15
+KPX e period 20
+KPX e comma 10
+
+KPX f quoteright 30
+KPX f quotedblright 30
+KPX f period -10
+KPX f o -20
+KPX f e -10
+KPX f comma -10
+
+KPX g g -10
+KPX g e 10
+
+KPX h y -20
+
+KPX k o -15
+
+KPX l y -15
+KPX l w -15
+
+KPX m y -30
+KPX m u -20
+
+KPX n y -20
+KPX n v -40
+KPX n u -10
+
+KPX o y -20
+KPX o x -30
+KPX o w -15
+KPX o v -20
+
+KPX p y -15
+
+KPX period space -40
+KPX period quoteright -120
+KPX period quotedblright -120
+
+KPX quotedblright space -80
+
+KPX quoteleft quoteleft -46
+
+KPX quoteright v -20
+KPX quoteright space -80
+KPX quoteright s -60
+KPX quoteright r -40
+KPX quoteright quoteright -46
+KPX quoteright l -20
+KPX quoteright d -80
+
+KPX r y 10
+KPX r v 10
+KPX r t 20
+KPX r s -15
+KPX r q -20
+KPX r period -60
+KPX r o -20
+KPX r hyphen -20
+KPX r g -15
+KPX r d -20
+KPX r comma -60
+KPX r c -20
+
+KPX s w -15
+
+KPX semicolon space -40
+
+KPX space quoteleft -60
+KPX space quotedblleft -80
+KPX space Y -120
+KPX space W -80
+KPX space V -80
+KPX space T -100
+
+KPX v period -80
+KPX v o -30
+KPX v comma -80
+KPX v a -20
+
+KPX w period -40
+KPX w o -20
+KPX w comma -40
+
+KPX x e -10
+
+KPX y period -80
+KPX y o -25
+KPX y e -10
+KPX y comma -80
+KPX y a -30
+
+KPX z e 10
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 192 186 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 192 186 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 192 186 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 192 186 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 192 186 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 192 186 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 176 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 169 186 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 169 186 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 169 186 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 169 186 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 10 186 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 10 186 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 10 186 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 10 186 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 192 186 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 215 186 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 215 186 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 215 186 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 215 186 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 186 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 169 186 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 192 186 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 192 186 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 192 186 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 192 186 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 169 186 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 169 186 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 146 186 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 92 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 92 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 92 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 92 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 92 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 92 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 108 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 92 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 92 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 92 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 92 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -22 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -22 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -22 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -22 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 114 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 114 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 114 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 114 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 114 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 114 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 92 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 114 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 114 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 114 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 114 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 92 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 92 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 69 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Narrow-Oblique.afm b/tlt3.0/library/afm/Helvetica-Narrow-Oblique.afm
new file mode 100644
index 0000000..0a8cb32
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Narrow-Oblique.afm
@@ -0,0 +1,613 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu Mar 15 11:25:48 1990
+Comment UniqueID 28389
+Comment VMusage 7572 42473
+FontName Helvetica-Narrow-Oblique
+FullName Helvetica Narrow Oblique
+FamilyName Helvetica
+Weight Medium
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -139 -225 915 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 228 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 228 ; N exclam ; B 74 0 278 718 ;
+C 34 ; WX 291 ; N quotedbl ; B 138 463 359 718 ;
+C 35 ; WX 456 ; N numbersign ; B 60 0 517 688 ;
+C 36 ; WX 456 ; N dollar ; B 57 -115 506 775 ;
+C 37 ; WX 729 ; N percent ; B 120 -19 729 703 ;
+C 38 ; WX 547 ; N ampersand ; B 63 -15 530 718 ;
+C 39 ; WX 182 ; N quoteright ; B 124 463 254 718 ;
+C 40 ; WX 273 ; N parenleft ; B 89 -207 372 733 ;
+C 41 ; WX 273 ; N parenright ; B -7 -207 276 733 ;
+C 42 ; WX 319 ; N asterisk ; B 135 431 389 718 ;
+C 43 ; WX 479 ; N plus ; B 70 0 497 505 ;
+C 44 ; WX 228 ; N comma ; B 46 -147 175 106 ;
+C 45 ; WX 273 ; N hyphen ; B 77 232 293 322 ;
+C 46 ; WX 228 ; N period ; B 71 0 175 106 ;
+C 47 ; WX 228 ; N slash ; B -17 -19 370 737 ;
+C 48 ; WX 456 ; N zero ; B 77 -19 499 703 ;
+C 49 ; WX 456 ; N one ; B 170 0 417 703 ;
+C 50 ; WX 456 ; N two ; B 21 0 506 703 ;
+C 51 ; WX 456 ; N three ; B 61 -19 500 703 ;
+C 52 ; WX 456 ; N four ; B 50 0 472 703 ;
+C 53 ; WX 456 ; N five ; B 55 -19 509 688 ;
+C 54 ; WX 456 ; N six ; B 74 -19 504 703 ;
+C 55 ; WX 456 ; N seven ; B 112 0 549 688 ;
+C 56 ; WX 456 ; N eight ; B 60 -19 497 703 ;
+C 57 ; WX 456 ; N nine ; B 67 -19 499 703 ;
+C 58 ; WX 228 ; N colon ; B 71 0 247 516 ;
+C 59 ; WX 228 ; N semicolon ; B 46 -147 247 516 ;
+C 60 ; WX 479 ; N less ; B 77 11 526 495 ;
+C 61 ; WX 479 ; N equal ; B 52 115 515 390 ;
+C 62 ; WX 479 ; N greater ; B 41 11 490 495 ;
+C 63 ; WX 456 ; N question ; B 132 0 500 727 ;
+C 64 ; WX 832 ; N at ; B 176 -19 791 737 ;
+C 65 ; WX 547 ; N A ; B 11 0 536 718 ;
+C 66 ; WX 547 ; N B ; B 61 0 583 718 ;
+C 67 ; WX 592 ; N C ; B 88 -19 640 737 ;
+C 68 ; WX 592 ; N D ; B 66 0 626 718 ;
+C 69 ; WX 547 ; N E ; B 71 0 625 718 ;
+C 70 ; WX 501 ; N F ; B 71 0 603 718 ;
+C 71 ; WX 638 ; N G ; B 91 -19 655 737 ;
+C 72 ; WX 592 ; N H ; B 63 0 655 718 ;
+C 73 ; WX 228 ; N I ; B 75 0 279 718 ;
+C 74 ; WX 410 ; N J ; B 39 -19 476 718 ;
+C 75 ; WX 547 ; N K ; B 62 0 662 718 ;
+C 76 ; WX 456 ; N L ; B 62 0 455 718 ;
+C 77 ; WX 683 ; N M ; B 60 0 749 718 ;
+C 78 ; WX 592 ; N N ; B 62 0 655 718 ;
+C 79 ; WX 638 ; N O ; B 86 -19 677 737 ;
+C 80 ; WX 547 ; N P ; B 71 0 604 718 ;
+C 81 ; WX 638 ; N Q ; B 86 -56 677 737 ;
+C 82 ; WX 592 ; N R ; B 72 0 634 718 ;
+C 83 ; WX 547 ; N S ; B 74 -19 584 737 ;
+C 84 ; WX 501 ; N T ; B 122 0 615 718 ;
+C 85 ; WX 592 ; N U ; B 101 -19 653 718 ;
+C 86 ; WX 547 ; N V ; B 142 0 656 718 ;
+C 87 ; WX 774 ; N W ; B 138 0 886 718 ;
+C 88 ; WX 547 ; N X ; B 16 0 647 718 ;
+C 89 ; WX 547 ; N Y ; B 137 0 661 718 ;
+C 90 ; WX 501 ; N Z ; B 19 0 607 718 ;
+C 91 ; WX 228 ; N bracketleft ; B 17 -196 331 722 ;
+C 92 ; WX 228 ; N backslash ; B 115 -19 239 737 ;
+C 93 ; WX 228 ; N bracketright ; B -11 -196 302 722 ;
+C 94 ; WX 385 ; N asciicircum ; B 35 264 442 688 ;
+C 95 ; WX 456 ; N underscore ; B -22 -125 443 -75 ;
+C 96 ; WX 182 ; N quoteleft ; B 135 470 265 725 ;
+C 97 ; WX 456 ; N a ; B 50 -15 458 538 ;
+C 98 ; WX 456 ; N b ; B 48 -15 479 718 ;
+C 99 ; WX 410 ; N c ; B 61 -15 454 538 ;
+C 100 ; WX 456 ; N d ; B 69 -15 534 718 ;
+C 101 ; WX 456 ; N e ; B 69 -15 474 538 ;
+C 102 ; WX 228 ; N f ; B 71 0 341 728 ; L i fi ; L l fl ;
+C 103 ; WX 456 ; N g ; B 34 -220 500 538 ;
+C 104 ; WX 456 ; N h ; B 53 0 470 718 ;
+C 105 ; WX 182 ; N i ; B 55 0 252 718 ;
+C 106 ; WX 182 ; N j ; B -49 -210 252 718 ;
+C 107 ; WX 410 ; N k ; B 55 0 492 718 ;
+C 108 ; WX 182 ; N l ; B 55 0 252 718 ;
+C 109 ; WX 683 ; N m ; B 53 0 699 538 ;
+C 110 ; WX 456 ; N n ; B 53 0 470 538 ;
+C 111 ; WX 456 ; N o ; B 68 -14 479 538 ;
+C 112 ; WX 456 ; N p ; B 11 -207 479 538 ;
+C 113 ; WX 456 ; N q ; B 69 -207 496 538 ;
+C 114 ; WX 273 ; N r ; B 63 0 365 538 ;
+C 115 ; WX 410 ; N s ; B 52 -15 434 538 ;
+C 116 ; WX 228 ; N t ; B 84 -7 302 669 ;
+C 117 ; WX 456 ; N u ; B 77 -15 492 523 ;
+C 118 ; WX 410 ; N v ; B 98 0 495 523 ;
+C 119 ; WX 592 ; N w ; B 103 0 673 523 ;
+C 120 ; WX 410 ; N x ; B 9 0 487 523 ;
+C 121 ; WX 410 ; N y ; B 12 -214 492 523 ;
+C 122 ; WX 410 ; N z ; B 25 0 468 523 ;
+C 123 ; WX 274 ; N braceleft ; B 75 -196 365 722 ;
+C 124 ; WX 213 ; N bar ; B 74 -19 265 737 ;
+C 125 ; WX 274 ; N braceright ; B 0 -196 291 722 ;
+C 126 ; WX 479 ; N asciitilde ; B 91 180 476 326 ;
+C 161 ; WX 273 ; N exclamdown ; B 63 -195 267 523 ;
+C 162 ; WX 456 ; N cent ; B 78 -115 479 623 ;
+C 163 ; WX 456 ; N sterling ; B 40 -16 520 718 ;
+C 164 ; WX 137 ; N fraction ; B -139 -19 396 703 ;
+C 165 ; WX 456 ; N yen ; B 67 0 573 688 ;
+C 166 ; WX 456 ; N florin ; B -43 -207 537 737 ;
+C 167 ; WX 456 ; N section ; B 63 -191 479 737 ;
+C 168 ; WX 456 ; N currency ; B 49 99 530 603 ;
+C 169 ; WX 157 ; N quotesingle ; B 129 463 233 718 ;
+C 170 ; WX 273 ; N quotedblleft ; B 113 470 378 725 ;
+C 171 ; WX 456 ; N guillemotleft ; B 120 108 454 446 ;
+C 172 ; WX 273 ; N guilsinglleft ; B 112 108 279 446 ;
+C 173 ; WX 273 ; N guilsinglright ; B 91 108 257 446 ;
+C 174 ; WX 410 ; N fi ; B 71 0 481 728 ;
+C 175 ; WX 410 ; N fl ; B 71 0 479 728 ;
+C 177 ; WX 456 ; N endash ; B 42 240 510 313 ;
+C 178 ; WX 456 ; N dagger ; B 110 -159 510 718 ;
+C 179 ; WX 456 ; N daggerdbl ; B 43 -159 511 718 ;
+C 180 ; WX 228 ; N periodcentered ; B 106 190 211 315 ;
+C 182 ; WX 440 ; N paragraph ; B 103 -173 533 718 ;
+C 183 ; WX 287 ; N bullet ; B 74 202 339 517 ;
+C 184 ; WX 182 ; N quotesinglbase ; B 17 -149 147 106 ;
+C 185 ; WX 273 ; N quotedblbase ; B -5 -149 260 106 ;
+C 186 ; WX 273 ; N quotedblright ; B 102 463 367 718 ;
+C 187 ; WX 456 ; N guillemotright ; B 98 108 433 446 ;
+C 188 ; WX 820 ; N ellipsis ; B 94 0 744 106 ;
+C 189 ; WX 820 ; N perthousand ; B 72 -19 844 703 ;
+C 191 ; WX 501 ; N questiondown ; B 70 -201 438 525 ;
+C 193 ; WX 273 ; N grave ; B 139 593 276 734 ;
+C 194 ; WX 273 ; N acute ; B 203 593 390 734 ;
+C 195 ; WX 273 ; N circumflex ; B 121 593 359 734 ;
+C 196 ; WX 273 ; N tilde ; B 102 606 402 722 ;
+C 197 ; WX 273 ; N macron ; B 117 627 384 684 ;
+C 198 ; WX 273 ; N breve ; B 137 595 391 731 ;
+C 199 ; WX 273 ; N dotaccent ; B 204 604 297 706 ;
+C 200 ; WX 273 ; N dieresis ; B 138 604 363 706 ;
+C 202 ; WX 273 ; N ring ; B 175 572 330 756 ;
+C 203 ; WX 273 ; N cedilla ; B 2 -225 191 0 ;
+C 205 ; WX 273 ; N hungarumlaut ; B 129 593 463 734 ;
+C 206 ; WX 273 ; N ogonek ; B 35 -225 204 0 ;
+C 207 ; WX 273 ; N caron ; B 145 593 384 734 ;
+C 208 ; WX 820 ; N emdash ; B 42 240 875 313 ;
+C 225 ; WX 820 ; N AE ; B 7 0 899 718 ;
+C 227 ; WX 303 ; N ordfeminine ; B 82 304 368 737 ;
+C 232 ; WX 456 ; N Lslash ; B 34 0 455 718 ;
+C 233 ; WX 638 ; N Oslash ; B 35 -19 730 737 ;
+C 234 ; WX 820 ; N OE ; B 80 -19 915 737 ;
+C 235 ; WX 299 ; N ordmasculine ; B 82 304 384 737 ;
+C 241 ; WX 729 ; N ae ; B 50 -15 746 538 ;
+C 245 ; WX 228 ; N dotlessi ; B 78 0 241 523 ;
+C 248 ; WX 182 ; N lslash ; B 34 0 284 718 ;
+C 249 ; WX 501 ; N oslash ; B 24 -22 531 545 ;
+C 250 ; WX 774 ; N oe ; B 68 -15 791 538 ;
+C 251 ; WX 501 ; N germandbls ; B 55 -15 539 728 ;
+C -1 ; WX 501 ; N Zcaron ; B 19 0 607 929 ;
+C -1 ; WX 410 ; N ccedilla ; B 61 -225 454 538 ;
+C -1 ; WX 410 ; N ydieresis ; B 12 -214 492 706 ;
+C -1 ; WX 456 ; N atilde ; B 50 -15 486 722 ;
+C -1 ; WX 228 ; N icircumflex ; B 78 0 337 734 ;
+C -1 ; WX 273 ; N threesuperior ; B 74 270 358 703 ;
+C -1 ; WX 456 ; N ecircumflex ; B 69 -15 474 734 ;
+C -1 ; WX 456 ; N thorn ; B 11 -207 479 718 ;
+C -1 ; WX 456 ; N egrave ; B 69 -15 474 734 ;
+C -1 ; WX 273 ; N twosuperior ; B 52 281 368 703 ;
+C -1 ; WX 456 ; N eacute ; B 69 -15 481 734 ;
+C -1 ; WX 456 ; N otilde ; B 68 -14 494 722 ;
+C -1 ; WX 547 ; N Aacute ; B 11 0 560 929 ;
+C -1 ; WX 456 ; N ocircumflex ; B 68 -14 479 734 ;
+C -1 ; WX 410 ; N yacute ; B 12 -214 492 734 ;
+C -1 ; WX 456 ; N udieresis ; B 77 -15 492 706 ;
+C -1 ; WX 684 ; N threequarters ; B 106 -19 706 703 ;
+C -1 ; WX 456 ; N acircumflex ; B 50 -15 458 734 ;
+C -1 ; WX 592 ; N Eth ; B 57 0 626 718 ;
+C -1 ; WX 456 ; N edieresis ; B 69 -15 474 706 ;
+C -1 ; WX 456 ; N ugrave ; B 77 -15 492 734 ;
+C -1 ; WX 820 ; N trademark ; B 152 306 866 718 ;
+C -1 ; WX 456 ; N ograve ; B 68 -14 479 734 ;
+C -1 ; WX 410 ; N scaron ; B 52 -15 453 734 ;
+C -1 ; WX 228 ; N Idieresis ; B 75 0 375 901 ;
+C -1 ; WX 456 ; N uacute ; B 77 -15 492 734 ;
+C -1 ; WX 456 ; N agrave ; B 50 -15 458 734 ;
+C -1 ; WX 456 ; N ntilde ; B 53 0 486 722 ;
+C -1 ; WX 456 ; N aring ; B 50 -15 458 756 ;
+C -1 ; WX 410 ; N zcaron ; B 25 0 468 734 ;
+C -1 ; WX 228 ; N Icircumflex ; B 75 0 371 929 ;
+C -1 ; WX 592 ; N Ntilde ; B 62 0 655 917 ;
+C -1 ; WX 456 ; N ucircumflex ; B 77 -15 492 734 ;
+C -1 ; WX 547 ; N Ecircumflex ; B 71 0 625 929 ;
+C -1 ; WX 228 ; N Iacute ; B 75 0 401 929 ;
+C -1 ; WX 592 ; N Ccedilla ; B 88 -225 640 737 ;
+C -1 ; WX 638 ; N Odieresis ; B 86 -19 677 901 ;
+C -1 ; WX 547 ; N Scaron ; B 74 -19 584 929 ;
+C -1 ; WX 547 ; N Edieresis ; B 71 0 625 901 ;
+C -1 ; WX 228 ; N Igrave ; B 75 0 288 929 ;
+C -1 ; WX 456 ; N adieresis ; B 50 -15 458 706 ;
+C -1 ; WX 638 ; N Ograve ; B 86 -19 677 929 ;
+C -1 ; WX 547 ; N Egrave ; B 71 0 625 929 ;
+C -1 ; WX 547 ; N Ydieresis ; B 137 0 661 901 ;
+C -1 ; WX 604 ; N registered ; B 44 -19 687 737 ;
+C -1 ; WX 638 ; N Otilde ; B 86 -19 677 917 ;
+C -1 ; WX 684 ; N onequarter ; B 123 -19 658 703 ;
+C -1 ; WX 592 ; N Ugrave ; B 101 -19 653 929 ;
+C -1 ; WX 592 ; N Ucircumflex ; B 101 -19 653 929 ;
+C -1 ; WX 547 ; N Thorn ; B 71 0 584 718 ;
+C -1 ; WX 479 ; N divide ; B 70 -19 497 524 ;
+C -1 ; WX 547 ; N Atilde ; B 11 0 573 917 ;
+C -1 ; WX 592 ; N Uacute ; B 101 -19 653 929 ;
+C -1 ; WX 638 ; N Ocircumflex ; B 86 -19 677 929 ;
+C -1 ; WX 479 ; N logicalnot ; B 87 108 515 390 ;
+C -1 ; WX 547 ; N Aring ; B 11 0 536 931 ;
+C -1 ; WX 228 ; N idieresis ; B 78 0 341 706 ;
+C -1 ; WX 228 ; N iacute ; B 78 0 367 734 ;
+C -1 ; WX 456 ; N aacute ; B 50 -15 481 734 ;
+C -1 ; WX 479 ; N plusminus ; B 32 0 507 506 ;
+C -1 ; WX 479 ; N multiply ; B 41 0 526 506 ;
+C -1 ; WX 592 ; N Udieresis ; B 101 -19 653 901 ;
+C -1 ; WX 479 ; N minus ; B 70 216 497 289 ;
+C -1 ; WX 273 ; N onesuperior ; B 136 281 305 703 ;
+C -1 ; WX 547 ; N Eacute ; B 71 0 625 929 ;
+C -1 ; WX 547 ; N Acircumflex ; B 11 0 536 929 ;
+C -1 ; WX 604 ; N copyright ; B 44 -19 687 737 ;
+C -1 ; WX 547 ; N Agrave ; B 11 0 536 929 ;
+C -1 ; WX 456 ; N odieresis ; B 68 -14 479 706 ;
+C -1 ; WX 456 ; N oacute ; B 68 -14 481 734 ;
+C -1 ; WX 328 ; N degree ; B 138 411 384 703 ;
+C -1 ; WX 228 ; N igrave ; B 78 0 254 734 ;
+C -1 ; WX 456 ; N mu ; B 20 -207 492 523 ;
+C -1 ; WX 638 ; N Oacute ; B 86 -19 677 929 ;
+C -1 ; WX 456 ; N eth ; B 67 -15 506 737 ;
+C -1 ; WX 547 ; N Adieresis ; B 11 0 536 901 ;
+C -1 ; WX 547 ; N Yacute ; B 137 0 661 929 ;
+C -1 ; WX 213 ; N brokenbar ; B 74 -19 265 737 ;
+C -1 ; WX 684 ; N onehalf ; B 93 -19 688 703 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 250
+
+KPX A y -40
+KPX A w -40
+KPX A v -40
+KPX A u -30
+KPX A Y -100
+KPX A W -50
+KPX A V -70
+KPX A U -50
+KPX A T -120
+KPX A Q -30
+KPX A O -30
+KPX A G -30
+KPX A C -30
+
+KPX B period -20
+KPX B comma -20
+KPX B U -10
+
+KPX C period -30
+KPX C comma -30
+
+KPX D period -70
+KPX D comma -70
+KPX D Y -90
+KPX D W -40
+KPX D V -70
+KPX D A -40
+
+KPX F r -45
+KPX F period -150
+KPX F o -30
+KPX F e -30
+KPX F comma -150
+KPX F a -50
+KPX F A -80
+
+KPX J u -20
+KPX J period -30
+KPX J comma -30
+KPX J a -20
+KPX J A -20
+
+KPX K y -50
+KPX K u -30
+KPX K o -40
+KPX K e -40
+KPX K O -50
+
+KPX L y -30
+KPX L quoteright -160
+KPX L quotedblright -140
+KPX L Y -140
+KPX L W -70
+KPX L V -110
+KPX L T -110
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -60
+KPX O W -30
+KPX O V -50
+KPX O T -40
+KPX O A -20
+
+KPX P period -180
+KPX P o -50
+KPX P e -50
+KPX P comma -180
+KPX P a -40
+KPX P A -120
+
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -30
+KPX R V -50
+KPX R U -40
+KPX R T -30
+KPX R O -20
+
+KPX S period -20
+KPX S comma -20
+
+KPX T y -120
+KPX T w -120
+KPX T u -120
+KPX T semicolon -20
+KPX T r -120
+KPX T period -120
+KPX T o -120
+KPX T hyphen -140
+KPX T e -120
+KPX T comma -120
+KPX T colon -20
+KPX T a -120
+KPX T O -40
+KPX T A -120
+
+KPX U period -40
+KPX U comma -40
+KPX U A -40
+
+KPX V u -70
+KPX V semicolon -40
+KPX V period -125
+KPX V o -80
+KPX V hyphen -80
+KPX V e -80
+KPX V comma -125
+KPX V colon -40
+KPX V a -70
+KPX V O -40
+KPX V G -40
+KPX V A -80
+
+KPX W y -20
+KPX W u -30
+KPX W period -80
+KPX W o -30
+KPX W hyphen -40
+KPX W e -30
+KPX W comma -80
+KPX W a -40
+KPX W O -20
+KPX W A -50
+
+KPX Y u -110
+KPX Y semicolon -60
+KPX Y period -140
+KPX Y o -140
+KPX Y i -20
+KPX Y hyphen -140
+KPX Y e -140
+KPX Y comma -140
+KPX Y colon -60
+KPX Y a -140
+KPX Y O -85
+KPX Y A -110
+
+KPX a y -30
+KPX a w -20
+KPX a v -20
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b period -40
+KPX b l -20
+KPX b comma -40
+KPX b b -10
+
+KPX c k -20
+KPX c comma -15
+
+KPX colon space -50
+
+KPX comma quoteright -100
+KPX comma quotedblright -100
+
+KPX e y -20
+KPX e x -30
+KPX e w -20
+KPX e v -30
+KPX e period -15
+KPX e comma -15
+
+KPX f quoteright 50
+KPX f quotedblright 60
+KPX f period -30
+KPX f o -30
+KPX f e -30
+KPX f dotlessi -28
+KPX f comma -30
+KPX f a -30
+
+KPX g r -10
+
+KPX h y -30
+
+KPX k o -20
+KPX k e -20
+
+KPX m y -15
+KPX m u -10
+
+KPX n y -15
+KPX n v -20
+KPX n u -10
+
+KPX o y -30
+KPX o x -30
+KPX o w -15
+KPX o v -15
+KPX o period -40
+KPX o comma -40
+
+KPX oslash z -55
+KPX oslash y -70
+KPX oslash x -85
+KPX oslash w -70
+KPX oslash v -70
+KPX oslash u -55
+KPX oslash t -55
+KPX oslash s -55
+KPX oslash r -55
+KPX oslash q -55
+KPX oslash period -95
+KPX oslash p -55
+KPX oslash o -55
+KPX oslash n -55
+KPX oslash m -55
+KPX oslash l -55
+KPX oslash k -55
+KPX oslash j -55
+KPX oslash i -55
+KPX oslash h -55
+KPX oslash g -55
+KPX oslash f -55
+KPX oslash e -55
+KPX oslash d -55
+KPX oslash comma -95
+KPX oslash c -55
+KPX oslash b -55
+KPX oslash a -55
+
+KPX p y -30
+KPX p period -35
+KPX p comma -35
+
+KPX period space -60
+KPX period quoteright -100
+KPX period quotedblright -100
+
+KPX quotedblright space -40
+
+KPX quoteleft quoteleft -57
+
+KPX quoteright space -70
+KPX quoteright s -50
+KPX quoteright r -50
+KPX quoteright quoteright -57
+KPX quoteright d -50
+
+KPX r y 30
+KPX r v 30
+KPX r u 15
+KPX r t 40
+KPX r semicolon 30
+KPX r period -50
+KPX r p 30
+KPX r n 25
+KPX r m 25
+KPX r l 15
+KPX r k 15
+KPX r i 15
+KPX r comma -50
+KPX r colon 30
+KPX r a -10
+
+KPX s w -30
+KPX s period -15
+KPX s comma -15
+
+KPX semicolon space -50
+
+KPX space quoteleft -60
+KPX space quotedblleft -30
+KPX space Y -90
+KPX space W -40
+KPX space V -50
+KPX space T -50
+
+KPX v period -80
+KPX v o -25
+KPX v e -25
+KPX v comma -80
+KPX v a -25
+
+KPX w period -60
+KPX w o -10
+KPX w e -10
+KPX w comma -60
+KPX w a -15
+
+KPX x e -30
+
+KPX y period -100
+KPX y o -20
+KPX y e -20
+KPX y comma -100
+KPX y a -20
+
+KPX z o -15
+KPX z e -15
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 171 195 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 171 195 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 171 195 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 171 195 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 167 175 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 171 195 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 160 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 171 195 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 171 195 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 171 195 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 171 195 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 12 195 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 12 195 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 12 195 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 12 195 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 202 195 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 217 195 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 217 195 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 217 195 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 217 195 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 217 195 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 171 195 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 194 195 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 194 195 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 194 195 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 194 195 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 171 195 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 171 195 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 148 195 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 92 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 92 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 92 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 92 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 92 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 69 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 92 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 92 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 92 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 92 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -22 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -22 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -22 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -22 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 92 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 92 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 92 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 92 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 92 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 69 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 92 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 92 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 92 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 92 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 69 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 69 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 69 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Narrow.afm b/tlt3.0/library/afm/Helvetica-Narrow.afm
new file mode 100644
index 0000000..2afeb75
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Narrow.afm
@@ -0,0 +1,613 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu Mar 15 11:04:57 1990
+Comment UniqueID 28380
+Comment VMusage 7572 42473
+FontName Helvetica-Narrow
+FullName Helvetica Narrow
+FamilyName Helvetica
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -136 -225 820 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 228 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 228 ; N exclam ; B 74 0 153 718 ;
+C 34 ; WX 291 ; N quotedbl ; B 57 463 234 718 ;
+C 35 ; WX 456 ; N numbersign ; B 23 0 434 688 ;
+C 36 ; WX 456 ; N dollar ; B 26 -115 426 775 ;
+C 37 ; WX 729 ; N percent ; B 32 -19 697 703 ;
+C 38 ; WX 547 ; N ampersand ; B 36 -15 529 718 ;
+C 39 ; WX 182 ; N quoteright ; B 43 463 129 718 ;
+C 40 ; WX 273 ; N parenleft ; B 56 -207 245 733 ;
+C 41 ; WX 273 ; N parenright ; B 28 -207 217 733 ;
+C 42 ; WX 319 ; N asterisk ; B 32 431 286 718 ;
+C 43 ; WX 479 ; N plus ; B 32 0 447 505 ;
+C 44 ; WX 228 ; N comma ; B 71 -147 157 106 ;
+C 45 ; WX 273 ; N hyphen ; B 36 232 237 322 ;
+C 46 ; WX 228 ; N period ; B 71 0 157 106 ;
+C 47 ; WX 228 ; N slash ; B -14 -19 242 737 ;
+C 48 ; WX 456 ; N zero ; B 30 -19 426 703 ;
+C 49 ; WX 456 ; N one ; B 83 0 294 703 ;
+C 50 ; WX 456 ; N two ; B 21 0 416 703 ;
+C 51 ; WX 456 ; N three ; B 28 -19 428 703 ;
+C 52 ; WX 456 ; N four ; B 20 0 429 703 ;
+C 53 ; WX 456 ; N five ; B 26 -19 421 688 ;
+C 54 ; WX 456 ; N six ; B 31 -19 425 703 ;
+C 55 ; WX 456 ; N seven ; B 30 0 429 688 ;
+C 56 ; WX 456 ; N eight ; B 31 -19 424 703 ;
+C 57 ; WX 456 ; N nine ; B 34 -19 421 703 ;
+C 58 ; WX 228 ; N colon ; B 71 0 157 516 ;
+C 59 ; WX 228 ; N semicolon ; B 71 -147 157 516 ;
+C 60 ; WX 479 ; N less ; B 39 11 440 495 ;
+C 61 ; WX 479 ; N equal ; B 32 115 447 390 ;
+C 62 ; WX 479 ; N greater ; B 39 11 440 495 ;
+C 63 ; WX 456 ; N question ; B 46 0 403 727 ;
+C 64 ; WX 832 ; N at ; B 121 -19 712 737 ;
+C 65 ; WX 547 ; N A ; B 11 0 536 718 ;
+C 66 ; WX 547 ; N B ; B 61 0 514 718 ;
+C 67 ; WX 592 ; N C ; B 36 -19 558 737 ;
+C 68 ; WX 592 ; N D ; B 66 0 553 718 ;
+C 69 ; WX 547 ; N E ; B 71 0 505 718 ;
+C 70 ; WX 501 ; N F ; B 71 0 478 718 ;
+C 71 ; WX 638 ; N G ; B 39 -19 577 737 ;
+C 72 ; WX 592 ; N H ; B 63 0 530 718 ;
+C 73 ; WX 228 ; N I ; B 75 0 154 718 ;
+C 74 ; WX 410 ; N J ; B 14 -19 351 718 ;
+C 75 ; WX 547 ; N K ; B 62 0 544 718 ;
+C 76 ; WX 456 ; N L ; B 62 0 440 718 ;
+C 77 ; WX 683 ; N M ; B 60 0 624 718 ;
+C 78 ; WX 592 ; N N ; B 62 0 530 718 ;
+C 79 ; WX 638 ; N O ; B 32 -19 606 737 ;
+C 80 ; WX 547 ; N P ; B 71 0 510 718 ;
+C 81 ; WX 638 ; N Q ; B 32 -56 606 737 ;
+C 82 ; WX 592 ; N R ; B 72 0 561 718 ;
+C 83 ; WX 547 ; N S ; B 40 -19 508 737 ;
+C 84 ; WX 501 ; N T ; B 11 0 490 718 ;
+C 85 ; WX 592 ; N U ; B 65 -19 528 718 ;
+C 86 ; WX 547 ; N V ; B 16 0 531 718 ;
+C 87 ; WX 774 ; N W ; B 13 0 761 718 ;
+C 88 ; WX 547 ; N X ; B 16 0 531 718 ;
+C 89 ; WX 547 ; N Y ; B 11 0 535 718 ;
+C 90 ; WX 501 ; N Z ; B 19 0 482 718 ;
+C 91 ; WX 228 ; N bracketleft ; B 52 -196 205 722 ;
+C 92 ; WX 228 ; N backslash ; B -14 -19 242 737 ;
+C 93 ; WX 228 ; N bracketright ; B 23 -196 176 722 ;
+C 94 ; WX 385 ; N asciicircum ; B -11 264 396 688 ;
+C 95 ; WX 456 ; N underscore ; B 0 -125 456 -75 ;
+C 96 ; WX 182 ; N quoteleft ; B 53 470 139 725 ;
+C 97 ; WX 456 ; N a ; B 30 -15 435 538 ;
+C 98 ; WX 456 ; N b ; B 48 -15 424 718 ;
+C 99 ; WX 410 ; N c ; B 25 -15 391 538 ;
+C 100 ; WX 456 ; N d ; B 29 -15 409 718 ;
+C 101 ; WX 456 ; N e ; B 33 -15 423 538 ;
+C 102 ; WX 228 ; N f ; B 11 0 215 728 ; L i fi ; L l fl ;
+C 103 ; WX 456 ; N g ; B 33 -220 409 538 ;
+C 104 ; WX 456 ; N h ; B 53 0 403 718 ;
+C 105 ; WX 182 ; N i ; B 55 0 127 718 ;
+C 106 ; WX 182 ; N j ; B -13 -210 127 718 ;
+C 107 ; WX 410 ; N k ; B 55 0 411 718 ;
+C 108 ; WX 182 ; N l ; B 55 0 127 718 ;
+C 109 ; WX 683 ; N m ; B 53 0 631 538 ;
+C 110 ; WX 456 ; N n ; B 53 0 403 538 ;
+C 111 ; WX 456 ; N o ; B 29 -14 427 538 ;
+C 112 ; WX 456 ; N p ; B 48 -207 424 538 ;
+C 113 ; WX 456 ; N q ; B 29 -207 405 538 ;
+C 114 ; WX 273 ; N r ; B 63 0 272 538 ;
+C 115 ; WX 410 ; N s ; B 26 -15 380 538 ;
+C 116 ; WX 228 ; N t ; B 11 -7 211 669 ;
+C 117 ; WX 456 ; N u ; B 56 -15 401 523 ;
+C 118 ; WX 410 ; N v ; B 7 0 403 523 ;
+C 119 ; WX 592 ; N w ; B 11 0 581 523 ;
+C 120 ; WX 410 ; N x ; B 9 0 402 523 ;
+C 121 ; WX 410 ; N y ; B 9 -214 401 523 ;
+C 122 ; WX 410 ; N z ; B 25 0 385 523 ;
+C 123 ; WX 274 ; N braceleft ; B 34 -196 239 722 ;
+C 124 ; WX 213 ; N bar ; B 77 -19 137 737 ;
+C 125 ; WX 274 ; N braceright ; B 34 -196 239 722 ;
+C 126 ; WX 479 ; N asciitilde ; B 50 180 429 326 ;
+C 161 ; WX 273 ; N exclamdown ; B 97 -195 176 523 ;
+C 162 ; WX 456 ; N cent ; B 42 -115 421 623 ;
+C 163 ; WX 456 ; N sterling ; B 27 -16 442 718 ;
+C 164 ; WX 137 ; N fraction ; B -136 -19 273 703 ;
+C 165 ; WX 456 ; N yen ; B 2 0 453 688 ;
+C 166 ; WX 456 ; N florin ; B -9 -207 411 737 ;
+C 167 ; WX 456 ; N section ; B 35 -191 420 737 ;
+C 168 ; WX 456 ; N currency ; B 23 99 433 603 ;
+C 169 ; WX 157 ; N quotesingle ; B 48 463 108 718 ;
+C 170 ; WX 273 ; N quotedblleft ; B 31 470 252 725 ;
+C 171 ; WX 456 ; N guillemotleft ; B 80 108 376 446 ;
+C 172 ; WX 273 ; N guilsinglleft ; B 72 108 201 446 ;
+C 173 ; WX 273 ; N guilsinglright ; B 72 108 201 446 ;
+C 174 ; WX 410 ; N fi ; B 11 0 356 728 ;
+C 175 ; WX 410 ; N fl ; B 11 0 354 728 ;
+C 177 ; WX 456 ; N endash ; B 0 240 456 313 ;
+C 178 ; WX 456 ; N dagger ; B 35 -159 421 718 ;
+C 179 ; WX 456 ; N daggerdbl ; B 35 -159 421 718 ;
+C 180 ; WX 228 ; N periodcentered ; B 63 190 166 315 ;
+C 182 ; WX 440 ; N paragraph ; B 15 -173 408 718 ;
+C 183 ; WX 287 ; N bullet ; B 15 202 273 517 ;
+C 184 ; WX 182 ; N quotesinglbase ; B 43 -149 129 106 ;
+C 185 ; WX 273 ; N quotedblbase ; B 21 -149 242 106 ;
+C 186 ; WX 273 ; N quotedblright ; B 21 463 242 718 ;
+C 187 ; WX 456 ; N guillemotright ; B 80 108 376 446 ;
+C 188 ; WX 820 ; N ellipsis ; B 94 0 726 106 ;
+C 189 ; WX 820 ; N perthousand ; B 6 -19 815 703 ;
+C 191 ; WX 501 ; N questiondown ; B 75 -201 432 525 ;
+C 193 ; WX 273 ; N grave ; B 11 593 173 734 ;
+C 194 ; WX 273 ; N acute ; B 100 593 262 734 ;
+C 195 ; WX 273 ; N circumflex ; B 17 593 256 734 ;
+C 196 ; WX 273 ; N tilde ; B -3 606 276 722 ;
+C 197 ; WX 273 ; N macron ; B 8 627 265 684 ;
+C 198 ; WX 273 ; N breve ; B 11 595 263 731 ;
+C 199 ; WX 273 ; N dotaccent ; B 99 604 174 706 ;
+C 200 ; WX 273 ; N dieresis ; B 33 604 240 706 ;
+C 202 ; WX 273 ; N ring ; B 61 572 212 756 ;
+C 203 ; WX 273 ; N cedilla ; B 37 -225 212 0 ;
+C 205 ; WX 273 ; N hungarumlaut ; B 25 593 335 734 ;
+C 206 ; WX 273 ; N ogonek ; B 60 -225 235 0 ;
+C 207 ; WX 273 ; N caron ; B 17 593 256 734 ;
+C 208 ; WX 820 ; N emdash ; B 0 240 820 313 ;
+C 225 ; WX 820 ; N AE ; B 7 0 780 718 ;
+C 227 ; WX 303 ; N ordfeminine ; B 20 304 284 737 ;
+C 232 ; WX 456 ; N Lslash ; B -16 0 440 718 ;
+C 233 ; WX 638 ; N Oslash ; B 32 -19 607 737 ;
+C 234 ; WX 820 ; N OE ; B 30 -19 791 737 ;
+C 235 ; WX 299 ; N ordmasculine ; B 20 304 280 737 ;
+C 241 ; WX 729 ; N ae ; B 30 -15 695 538 ;
+C 245 ; WX 228 ; N dotlessi ; B 78 0 150 523 ;
+C 248 ; WX 182 ; N lslash ; B -16 0 198 718 ;
+C 249 ; WX 501 ; N oslash ; B 23 -22 440 545 ;
+C 250 ; WX 774 ; N oe ; B 29 -15 740 538 ;
+C 251 ; WX 501 ; N germandbls ; B 55 -15 468 728 ;
+C -1 ; WX 501 ; N Zcaron ; B 19 0 482 929 ;
+C -1 ; WX 410 ; N ccedilla ; B 25 -225 391 538 ;
+C -1 ; WX 410 ; N ydieresis ; B 9 -214 401 706 ;
+C -1 ; WX 456 ; N atilde ; B 30 -15 435 722 ;
+C -1 ; WX 228 ; N icircumflex ; B -5 0 234 734 ;
+C -1 ; WX 273 ; N threesuperior ; B 4 270 266 703 ;
+C -1 ; WX 456 ; N ecircumflex ; B 33 -15 423 734 ;
+C -1 ; WX 456 ; N thorn ; B 48 -207 424 718 ;
+C -1 ; WX 456 ; N egrave ; B 33 -15 423 734 ;
+C -1 ; WX 273 ; N twosuperior ; B 3 281 265 703 ;
+C -1 ; WX 456 ; N eacute ; B 33 -15 423 734 ;
+C -1 ; WX 456 ; N otilde ; B 29 -14 427 722 ;
+C -1 ; WX 547 ; N Aacute ; B 11 0 536 929 ;
+C -1 ; WX 456 ; N ocircumflex ; B 29 -14 427 734 ;
+C -1 ; WX 410 ; N yacute ; B 9 -214 401 734 ;
+C -1 ; WX 456 ; N udieresis ; B 56 -15 401 706 ;
+C -1 ; WX 684 ; N threequarters ; B 37 -19 664 703 ;
+C -1 ; WX 456 ; N acircumflex ; B 30 -15 435 734 ;
+C -1 ; WX 592 ; N Eth ; B 0 0 553 718 ;
+C -1 ; WX 456 ; N edieresis ; B 33 -15 423 706 ;
+C -1 ; WX 456 ; N ugrave ; B 56 -15 401 734 ;
+C -1 ; WX 820 ; N trademark ; B 38 306 740 718 ;
+C -1 ; WX 456 ; N ograve ; B 29 -14 427 734 ;
+C -1 ; WX 410 ; N scaron ; B 26 -15 380 734 ;
+C -1 ; WX 228 ; N Idieresis ; B 11 0 218 901 ;
+C -1 ; WX 456 ; N uacute ; B 56 -15 401 734 ;
+C -1 ; WX 456 ; N agrave ; B 30 -15 435 734 ;
+C -1 ; WX 456 ; N ntilde ; B 53 0 403 722 ;
+C -1 ; WX 456 ; N aring ; B 30 -15 435 756 ;
+C -1 ; WX 410 ; N zcaron ; B 25 0 385 734 ;
+C -1 ; WX 228 ; N Icircumflex ; B -5 0 234 929 ;
+C -1 ; WX 592 ; N Ntilde ; B 62 0 530 917 ;
+C -1 ; WX 456 ; N ucircumflex ; B 56 -15 401 734 ;
+C -1 ; WX 547 ; N Ecircumflex ; B 71 0 505 929 ;
+C -1 ; WX 228 ; N Iacute ; B 75 0 239 929 ;
+C -1 ; WX 592 ; N Ccedilla ; B 36 -225 558 737 ;
+C -1 ; WX 638 ; N Odieresis ; B 32 -19 606 901 ;
+C -1 ; WX 547 ; N Scaron ; B 40 -19 508 929 ;
+C -1 ; WX 547 ; N Edieresis ; B 71 0 505 901 ;
+C -1 ; WX 228 ; N Igrave ; B -11 0 154 929 ;
+C -1 ; WX 456 ; N adieresis ; B 30 -15 435 706 ;
+C -1 ; WX 638 ; N Ograve ; B 32 -19 606 929 ;
+C -1 ; WX 547 ; N Egrave ; B 71 0 505 929 ;
+C -1 ; WX 547 ; N Ydieresis ; B 11 0 535 901 ;
+C -1 ; WX 604 ; N registered ; B -11 -19 617 737 ;
+C -1 ; WX 638 ; N Otilde ; B 32 -19 606 917 ;
+C -1 ; WX 684 ; N onequarter ; B 60 -19 620 703 ;
+C -1 ; WX 592 ; N Ugrave ; B 65 -19 528 929 ;
+C -1 ; WX 592 ; N Ucircumflex ; B 65 -19 528 929 ;
+C -1 ; WX 547 ; N Thorn ; B 71 0 510 718 ;
+C -1 ; WX 479 ; N divide ; B 32 -19 447 524 ;
+C -1 ; WX 547 ; N Atilde ; B 11 0 536 917 ;
+C -1 ; WX 592 ; N Uacute ; B 65 -19 528 929 ;
+C -1 ; WX 638 ; N Ocircumflex ; B 32 -19 606 929 ;
+C -1 ; WX 479 ; N logicalnot ; B 32 108 447 390 ;
+C -1 ; WX 547 ; N Aring ; B 11 0 536 931 ;
+C -1 ; WX 228 ; N idieresis ; B 11 0 218 706 ;
+C -1 ; WX 228 ; N iacute ; B 78 0 239 734 ;
+C -1 ; WX 456 ; N aacute ; B 30 -15 435 734 ;
+C -1 ; WX 479 ; N plusminus ; B 32 0 447 506 ;
+C -1 ; WX 479 ; N multiply ; B 32 0 447 506 ;
+C -1 ; WX 592 ; N Udieresis ; B 65 -19 528 901 ;
+C -1 ; WX 479 ; N minus ; B 32 216 447 289 ;
+C -1 ; WX 273 ; N onesuperior ; B 35 281 182 703 ;
+C -1 ; WX 547 ; N Eacute ; B 71 0 505 929 ;
+C -1 ; WX 547 ; N Acircumflex ; B 11 0 536 929 ;
+C -1 ; WX 604 ; N copyright ; B -11 -19 617 737 ;
+C -1 ; WX 547 ; N Agrave ; B 11 0 536 929 ;
+C -1 ; WX 456 ; N odieresis ; B 29 -14 427 706 ;
+C -1 ; WX 456 ; N oacute ; B 29 -14 427 734 ;
+C -1 ; WX 328 ; N degree ; B 44 411 284 703 ;
+C -1 ; WX 228 ; N igrave ; B -11 0 151 734 ;
+C -1 ; WX 456 ; N mu ; B 56 -207 401 523 ;
+C -1 ; WX 638 ; N Oacute ; B 32 -19 606 929 ;
+C -1 ; WX 456 ; N eth ; B 29 -15 428 737 ;
+C -1 ; WX 547 ; N Adieresis ; B 11 0 536 901 ;
+C -1 ; WX 547 ; N Yacute ; B 11 0 535 929 ;
+C -1 ; WX 213 ; N brokenbar ; B 77 -19 137 737 ;
+C -1 ; WX 684 ; N onehalf ; B 35 -19 634 703 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 250
+
+KPX A y -32
+KPX A w -32
+KPX A v -32
+KPX A u -24
+KPX A Y -81
+KPX A W -40
+KPX A V -56
+KPX A U -40
+KPX A T -97
+KPX A Q -24
+KPX A O -24
+KPX A G -24
+KPX A C -24
+
+KPX B period -15
+KPX B comma -15
+KPX B U -7
+
+KPX C period -24
+KPX C comma -24
+
+KPX D period -56
+KPX D comma -56
+KPX D Y -73
+KPX D W -32
+KPX D V -56
+KPX D A -32
+
+KPX F r -36
+KPX F period -122
+KPX F o -24
+KPX F e -24
+KPX F comma -122
+KPX F a -40
+KPX F A -65
+
+KPX J u -15
+KPX J period -24
+KPX J comma -24
+KPX J a -15
+KPX J A -15
+
+KPX K y -40
+KPX K u -24
+KPX K o -32
+KPX K e -32
+KPX K O -40
+
+KPX L y -24
+KPX L quoteright -130
+KPX L quotedblright -114
+KPX L Y -114
+KPX L W -56
+KPX L V -89
+KPX L T -89
+
+KPX O period -32
+KPX O comma -32
+KPX O Y -56
+KPX O X -48
+KPX O W -24
+KPX O V -40
+KPX O T -32
+KPX O A -15
+
+KPX P period -147
+KPX P o -40
+KPX P e -40
+KPX P comma -147
+KPX P a -32
+KPX P A -97
+
+KPX Q U -7
+
+KPX R Y -40
+KPX R W -24
+KPX R V -40
+KPX R U -32
+KPX R T -24
+KPX R O -15
+
+KPX S period -15
+KPX S comma -15
+
+KPX T y -97
+KPX T w -97
+KPX T u -97
+KPX T semicolon -15
+KPX T r -97
+KPX T period -97
+KPX T o -97
+KPX T hyphen -114
+KPX T e -97
+KPX T comma -97
+KPX T colon -15
+KPX T a -97
+KPX T O -32
+KPX T A -97
+
+KPX U period -32
+KPX U comma -32
+KPX U A -32
+
+KPX V u -56
+KPX V semicolon -32
+KPX V period -102
+KPX V o -65
+KPX V hyphen -65
+KPX V e -65
+KPX V comma -102
+KPX V colon -32
+KPX V a -56
+KPX V O -32
+KPX V G -32
+KPX V A -65
+
+KPX W y -15
+KPX W u -24
+KPX W period -65
+KPX W o -24
+KPX W hyphen -32
+KPX W e -24
+KPX W comma -65
+KPX W a -32
+KPX W O -15
+KPX W A -40
+
+KPX Y u -89
+KPX Y semicolon -48
+KPX Y period -114
+KPX Y o -114
+KPX Y i -15
+KPX Y hyphen -114
+KPX Y e -114
+KPX Y comma -114
+KPX Y colon -48
+KPX Y a -114
+KPX Y O -69
+KPX Y A -89
+
+KPX a y -24
+KPX a w -15
+KPX a v -15
+
+KPX b y -15
+KPX b v -15
+KPX b u -15
+KPX b period -32
+KPX b l -15
+KPX b comma -32
+KPX b b -7
+
+KPX c k -15
+KPX c comma -11
+
+KPX colon space -40
+
+KPX comma quoteright -81
+KPX comma quotedblright -81
+
+KPX e y -15
+KPX e x -24
+KPX e w -15
+KPX e v -24
+KPX e period -11
+KPX e comma -11
+
+KPX f quoteright 41
+KPX f quotedblright 49
+KPX f period -24
+KPX f o -24
+KPX f e -24
+KPX f dotlessi -22
+KPX f comma -24
+KPX f a -24
+
+KPX g r -7
+
+KPX h y -24
+
+KPX k o -15
+KPX k e -15
+
+KPX m y -11
+KPX m u -7
+
+KPX n y -11
+KPX n v -15
+KPX n u -7
+
+KPX o y -24
+KPX o x -24
+KPX o w -11
+KPX o v -11
+KPX o period -32
+KPX o comma -32
+
+KPX oslash z -44
+KPX oslash y -56
+KPX oslash x -69
+KPX oslash w -56
+KPX oslash v -56
+KPX oslash u -44
+KPX oslash t -44
+KPX oslash s -44
+KPX oslash r -44
+KPX oslash q -44
+KPX oslash period -77
+KPX oslash p -44
+KPX oslash o -44
+KPX oslash n -44
+KPX oslash m -44
+KPX oslash l -44
+KPX oslash k -44
+KPX oslash j -44
+KPX oslash i -44
+KPX oslash h -44
+KPX oslash g -44
+KPX oslash f -44
+KPX oslash e -44
+KPX oslash d -44
+KPX oslash comma -77
+KPX oslash c -44
+KPX oslash b -44
+KPX oslash a -44
+
+KPX p y -24
+KPX p period -28
+KPX p comma -28
+
+KPX period space -48
+KPX period quoteright -81
+KPX period quotedblright -81
+
+KPX quotedblright space -32
+
+KPX quoteleft quoteleft -46
+
+KPX quoteright space -56
+KPX quoteright s -40
+KPX quoteright r -40
+KPX quoteright quoteright -46
+KPX quoteright d -40
+
+KPX r y 25
+KPX r v 25
+KPX r u 12
+KPX r t 33
+KPX r semicolon 25
+KPX r period -40
+KPX r p 25
+KPX r n 21
+KPX r m 21
+KPX r l 12
+KPX r k 12
+KPX r i 12
+KPX r comma -40
+KPX r colon 25
+KPX r a -7
+
+KPX s w -24
+KPX s period -11
+KPX s comma -11
+
+KPX semicolon space -40
+
+KPX space quoteleft -48
+KPX space quotedblleft -24
+KPX space Y -73
+KPX space W -32
+KPX space V -40
+KPX space T -40
+
+KPX v period -65
+KPX v o -20
+KPX v e -20
+KPX v comma -65
+KPX v a -20
+
+KPX w period -48
+KPX w o -7
+KPX w e -7
+KPX w comma -48
+KPX w a -11
+
+KPX x e -24
+
+KPX y period -81
+KPX y o -15
+KPX y e -15
+KPX y comma -81
+KPX y a -15
+
+KPX z o -11
+KPX z e -11
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 137 195 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 137 195 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 137 195 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 137 195 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 137 175 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 137 195 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 160 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 137 195 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 137 195 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 137 195 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 137 195 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -22 195 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -22 195 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -22 195 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -22 195 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 168 195 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 183 195 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 183 195 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 183 195 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 183 195 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 183 195 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 137 195 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 160 195 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 160 195 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 160 195 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 160 195 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 137 195 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 137 195 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 114 195 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 92 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 92 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 92 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 92 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 92 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 69 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 92 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 92 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 92 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 92 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -22 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -22 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -22 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -22 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 92 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 92 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 92 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 92 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 92 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 69 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 92 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 92 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 92 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 92 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 69 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 69 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 69 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica-Oblique.afm b/tlt3.0/library/afm/Helvetica-Oblique.afm
new file mode 100644
index 0000000..4f0476f
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica-Oblique.afm
@@ -0,0 +1,613 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu Mar 15 10:24:18 1990
+Comment UniqueID 28362
+Comment VMusage 7572 42473
+FontName Helvetica-Oblique
+FullName Helvetica Oblique
+FamilyName Helvetica
+Weight Medium
+ItalicAngle -12
+IsFixedPitch false
+FontBBox -170 -225 1116 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 90 0 340 718 ;
+C 34 ; WX 355 ; N quotedbl ; B 168 463 438 718 ;
+C 35 ; WX 556 ; N numbersign ; B 73 0 631 688 ;
+C 36 ; WX 556 ; N dollar ; B 69 -115 617 775 ;
+C 37 ; WX 889 ; N percent ; B 147 -19 889 703 ;
+C 38 ; WX 667 ; N ampersand ; B 77 -15 647 718 ;
+C 39 ; WX 222 ; N quoteright ; B 151 463 310 718 ;
+C 40 ; WX 333 ; N parenleft ; B 108 -207 454 733 ;
+C 41 ; WX 333 ; N parenright ; B -9 -207 337 733 ;
+C 42 ; WX 389 ; N asterisk ; B 165 431 475 718 ;
+C 43 ; WX 584 ; N plus ; B 85 0 606 505 ;
+C 44 ; WX 278 ; N comma ; B 56 -147 214 106 ;
+C 45 ; WX 333 ; N hyphen ; B 93 232 357 322 ;
+C 46 ; WX 278 ; N period ; B 87 0 214 106 ;
+C 47 ; WX 278 ; N slash ; B -21 -19 452 737 ;
+C 48 ; WX 556 ; N zero ; B 93 -19 608 703 ;
+C 49 ; WX 556 ; N one ; B 207 0 508 703 ;
+C 50 ; WX 556 ; N two ; B 26 0 617 703 ;
+C 51 ; WX 556 ; N three ; B 75 -19 610 703 ;
+C 52 ; WX 556 ; N four ; B 61 0 576 703 ;
+C 53 ; WX 556 ; N five ; B 68 -19 621 688 ;
+C 54 ; WX 556 ; N six ; B 91 -19 615 703 ;
+C 55 ; WX 556 ; N seven ; B 137 0 669 688 ;
+C 56 ; WX 556 ; N eight ; B 74 -19 607 703 ;
+C 57 ; WX 556 ; N nine ; B 82 -19 609 703 ;
+C 58 ; WX 278 ; N colon ; B 87 0 301 516 ;
+C 59 ; WX 278 ; N semicolon ; B 56 -147 301 516 ;
+C 60 ; WX 584 ; N less ; B 94 11 641 495 ;
+C 61 ; WX 584 ; N equal ; B 63 115 628 390 ;
+C 62 ; WX 584 ; N greater ; B 50 11 597 495 ;
+C 63 ; WX 556 ; N question ; B 161 0 610 727 ;
+C 64 ; WX 1015 ; N at ; B 215 -19 965 737 ;
+C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
+C 66 ; WX 667 ; N B ; B 74 0 712 718 ;
+C 67 ; WX 722 ; N C ; B 108 -19 782 737 ;
+C 68 ; WX 722 ; N D ; B 81 0 764 718 ;
+C 69 ; WX 667 ; N E ; B 86 0 762 718 ;
+C 70 ; WX 611 ; N F ; B 86 0 736 718 ;
+C 71 ; WX 778 ; N G ; B 111 -19 799 737 ;
+C 72 ; WX 722 ; N H ; B 77 0 799 718 ;
+C 73 ; WX 278 ; N I ; B 91 0 341 718 ;
+C 74 ; WX 500 ; N J ; B 47 -19 581 718 ;
+C 75 ; WX 667 ; N K ; B 76 0 808 718 ;
+C 76 ; WX 556 ; N L ; B 76 0 555 718 ;
+C 77 ; WX 833 ; N M ; B 73 0 914 718 ;
+C 78 ; WX 722 ; N N ; B 76 0 799 718 ;
+C 79 ; WX 778 ; N O ; B 105 -19 826 737 ;
+C 80 ; WX 667 ; N P ; B 86 0 737 718 ;
+C 81 ; WX 778 ; N Q ; B 105 -56 826 737 ;
+C 82 ; WX 722 ; N R ; B 88 0 773 718 ;
+C 83 ; WX 667 ; N S ; B 90 -19 713 737 ;
+C 84 ; WX 611 ; N T ; B 148 0 750 718 ;
+C 85 ; WX 722 ; N U ; B 123 -19 797 718 ;
+C 86 ; WX 667 ; N V ; B 173 0 800 718 ;
+C 87 ; WX 944 ; N W ; B 169 0 1081 718 ;
+C 88 ; WX 667 ; N X ; B 19 0 790 718 ;
+C 89 ; WX 667 ; N Y ; B 167 0 806 718 ;
+C 90 ; WX 611 ; N Z ; B 23 0 741 718 ;
+C 91 ; WX 278 ; N bracketleft ; B 21 -196 403 722 ;
+C 92 ; WX 278 ; N backslash ; B 140 -19 291 737 ;
+C 93 ; WX 278 ; N bracketright ; B -14 -196 368 722 ;
+C 94 ; WX 469 ; N asciicircum ; B 42 264 539 688 ;
+C 95 ; WX 556 ; N underscore ; B -27 -125 540 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 165 470 323 725 ;
+C 97 ; WX 556 ; N a ; B 61 -15 559 538 ;
+C 98 ; WX 556 ; N b ; B 58 -15 584 718 ;
+C 99 ; WX 500 ; N c ; B 74 -15 553 538 ;
+C 100 ; WX 556 ; N d ; B 84 -15 652 718 ;
+C 101 ; WX 556 ; N e ; B 84 -15 578 538 ;
+C 102 ; WX 278 ; N f ; B 86 0 416 728 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 42 -220 610 538 ;
+C 104 ; WX 556 ; N h ; B 65 0 573 718 ;
+C 105 ; WX 222 ; N i ; B 67 0 308 718 ;
+C 106 ; WX 222 ; N j ; B -60 -210 308 718 ;
+C 107 ; WX 500 ; N k ; B 67 0 600 718 ;
+C 108 ; WX 222 ; N l ; B 67 0 308 718 ;
+C 109 ; WX 833 ; N m ; B 65 0 852 538 ;
+C 110 ; WX 556 ; N n ; B 65 0 573 538 ;
+C 111 ; WX 556 ; N o ; B 83 -14 585 538 ;
+C 112 ; WX 556 ; N p ; B 14 -207 584 538 ;
+C 113 ; WX 556 ; N q ; B 84 -207 605 538 ;
+C 114 ; WX 333 ; N r ; B 77 0 446 538 ;
+C 115 ; WX 500 ; N s ; B 63 -15 529 538 ;
+C 116 ; WX 278 ; N t ; B 102 -7 368 669 ;
+C 117 ; WX 556 ; N u ; B 94 -15 600 523 ;
+C 118 ; WX 500 ; N v ; B 119 0 603 523 ;
+C 119 ; WX 722 ; N w ; B 125 0 820 523 ;
+C 120 ; WX 500 ; N x ; B 11 0 594 523 ;
+C 121 ; WX 500 ; N y ; B 15 -214 600 523 ;
+C 122 ; WX 500 ; N z ; B 31 0 571 523 ;
+C 123 ; WX 334 ; N braceleft ; B 92 -196 445 722 ;
+C 124 ; WX 260 ; N bar ; B 90 -19 324 737 ;
+C 125 ; WX 334 ; N braceright ; B 0 -196 354 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 111 180 580 326 ;
+C 161 ; WX 333 ; N exclamdown ; B 77 -195 326 523 ;
+C 162 ; WX 556 ; N cent ; B 95 -115 584 623 ;
+C 163 ; WX 556 ; N sterling ; B 49 -16 634 718 ;
+C 164 ; WX 167 ; N fraction ; B -170 -19 482 703 ;
+C 165 ; WX 556 ; N yen ; B 81 0 699 688 ;
+C 166 ; WX 556 ; N florin ; B -52 -207 654 737 ;
+C 167 ; WX 556 ; N section ; B 76 -191 584 737 ;
+C 168 ; WX 556 ; N currency ; B 60 99 646 603 ;
+C 169 ; WX 191 ; N quotesingle ; B 157 463 285 718 ;
+C 170 ; WX 333 ; N quotedblleft ; B 138 470 461 725 ;
+C 171 ; WX 556 ; N guillemotleft ; B 146 108 554 446 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 137 108 340 446 ;
+C 173 ; WX 333 ; N guilsinglright ; B 111 108 314 446 ;
+C 174 ; WX 500 ; N fi ; B 86 0 587 728 ;
+C 175 ; WX 500 ; N fl ; B 86 0 585 728 ;
+C 177 ; WX 556 ; N endash ; B 51 240 623 313 ;
+C 178 ; WX 556 ; N dagger ; B 135 -159 622 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 52 -159 623 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 129 190 257 315 ;
+C 182 ; WX 537 ; N paragraph ; B 126 -173 650 718 ;
+C 183 ; WX 350 ; N bullet ; B 91 202 413 517 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 21 -149 180 106 ;
+C 185 ; WX 333 ; N quotedblbase ; B -6 -149 318 106 ;
+C 186 ; WX 333 ; N quotedblright ; B 124 463 448 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 120 108 528 446 ;
+C 188 ; WX 1000 ; N ellipsis ; B 115 0 908 106 ;
+C 189 ; WX 1000 ; N perthousand ; B 88 -19 1029 703 ;
+C 191 ; WX 611 ; N questiondown ; B 85 -201 534 525 ;
+C 193 ; WX 333 ; N grave ; B 170 593 337 734 ;
+C 194 ; WX 333 ; N acute ; B 248 593 475 734 ;
+C 195 ; WX 333 ; N circumflex ; B 147 593 438 734 ;
+C 196 ; WX 333 ; N tilde ; B 125 606 490 722 ;
+C 197 ; WX 333 ; N macron ; B 143 627 468 684 ;
+C 198 ; WX 333 ; N breve ; B 167 595 476 731 ;
+C 199 ; WX 333 ; N dotaccent ; B 249 604 362 706 ;
+C 200 ; WX 333 ; N dieresis ; B 168 604 443 706 ;
+C 202 ; WX 333 ; N ring ; B 214 572 402 756 ;
+C 203 ; WX 333 ; N cedilla ; B 2 -225 232 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 157 593 565 734 ;
+C 206 ; WX 333 ; N ogonek ; B 43 -225 249 0 ;
+C 207 ; WX 333 ; N caron ; B 177 593 468 734 ;
+C 208 ; WX 1000 ; N emdash ; B 51 240 1067 313 ;
+C 225 ; WX 1000 ; N AE ; B 8 0 1097 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 100 304 449 737 ;
+C 232 ; WX 556 ; N Lslash ; B 41 0 555 718 ;
+C 233 ; WX 778 ; N Oslash ; B 43 -19 890 737 ;
+C 234 ; WX 1000 ; N OE ; B 98 -19 1116 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 100 304 468 737 ;
+C 241 ; WX 889 ; N ae ; B 61 -15 909 538 ;
+C 245 ; WX 278 ; N dotlessi ; B 95 0 294 523 ;
+C 248 ; WX 222 ; N lslash ; B 41 0 347 718 ;
+C 249 ; WX 611 ; N oslash ; B 29 -22 647 545 ;
+C 250 ; WX 944 ; N oe ; B 83 -15 964 538 ;
+C 251 ; WX 611 ; N germandbls ; B 67 -15 658 728 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 741 929 ;
+C -1 ; WX 500 ; N ccedilla ; B 74 -225 553 538 ;
+C -1 ; WX 500 ; N ydieresis ; B 15 -214 600 706 ;
+C -1 ; WX 556 ; N atilde ; B 61 -15 592 722 ;
+C -1 ; WX 278 ; N icircumflex ; B 95 0 411 734 ;
+C -1 ; WX 333 ; N threesuperior ; B 90 270 436 703 ;
+C -1 ; WX 556 ; N ecircumflex ; B 84 -15 578 734 ;
+C -1 ; WX 556 ; N thorn ; B 14 -207 584 718 ;
+C -1 ; WX 556 ; N egrave ; B 84 -15 578 734 ;
+C -1 ; WX 333 ; N twosuperior ; B 64 281 449 703 ;
+C -1 ; WX 556 ; N eacute ; B 84 -15 587 734 ;
+C -1 ; WX 556 ; N otilde ; B 83 -14 602 722 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 683 929 ;
+C -1 ; WX 556 ; N ocircumflex ; B 83 -14 585 734 ;
+C -1 ; WX 500 ; N yacute ; B 15 -214 600 734 ;
+C -1 ; WX 556 ; N udieresis ; B 94 -15 600 706 ;
+C -1 ; WX 834 ; N threequarters ; B 130 -19 861 703 ;
+C -1 ; WX 556 ; N acircumflex ; B 61 -15 559 734 ;
+C -1 ; WX 722 ; N Eth ; B 69 0 764 718 ;
+C -1 ; WX 556 ; N edieresis ; B 84 -15 578 706 ;
+C -1 ; WX 556 ; N ugrave ; B 94 -15 600 734 ;
+C -1 ; WX 1000 ; N trademark ; B 186 306 1056 718 ;
+C -1 ; WX 556 ; N ograve ; B 83 -14 585 734 ;
+C -1 ; WX 500 ; N scaron ; B 63 -15 552 734 ;
+C -1 ; WX 278 ; N Idieresis ; B 91 0 458 901 ;
+C -1 ; WX 556 ; N uacute ; B 94 -15 600 734 ;
+C -1 ; WX 556 ; N agrave ; B 61 -15 559 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 592 722 ;
+C -1 ; WX 556 ; N aring ; B 61 -15 559 756 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 571 734 ;
+C -1 ; WX 278 ; N Icircumflex ; B 91 0 452 929 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 799 917 ;
+C -1 ; WX 556 ; N ucircumflex ; B 94 -15 600 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 762 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 489 929 ;
+C -1 ; WX 722 ; N Ccedilla ; B 108 -225 782 737 ;
+C -1 ; WX 778 ; N Odieresis ; B 105 -19 826 901 ;
+C -1 ; WX 667 ; N Scaron ; B 90 -19 713 929 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 762 901 ;
+C -1 ; WX 278 ; N Igrave ; B 91 0 351 929 ;
+C -1 ; WX 556 ; N adieresis ; B 61 -15 559 706 ;
+C -1 ; WX 778 ; N Ograve ; B 105 -19 826 929 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 762 929 ;
+C -1 ; WX 667 ; N Ydieresis ; B 167 0 806 901 ;
+C -1 ; WX 737 ; N registered ; B 54 -19 837 737 ;
+C -1 ; WX 778 ; N Otilde ; B 105 -19 826 917 ;
+C -1 ; WX 834 ; N onequarter ; B 150 -19 802 703 ;
+C -1 ; WX 722 ; N Ugrave ; B 123 -19 797 929 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 123 -19 797 929 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 712 718 ;
+C -1 ; WX 584 ; N divide ; B 85 -19 606 524 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 699 917 ;
+C -1 ; WX 722 ; N Uacute ; B 123 -19 797 929 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 105 -19 826 929 ;
+C -1 ; WX 584 ; N logicalnot ; B 106 108 628 390 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 278 ; N idieresis ; B 95 0 416 706 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 448 734 ;
+C -1 ; WX 556 ; N aacute ; B 61 -15 587 734 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 618 506 ;
+C -1 ; WX 584 ; N multiply ; B 50 0 642 506 ;
+C -1 ; WX 722 ; N Udieresis ; B 123 -19 797 901 ;
+C -1 ; WX 584 ; N minus ; B 85 216 606 289 ;
+C -1 ; WX 333 ; N onesuperior ; B 166 281 371 703 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 762 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 737 ; N copyright ; B 54 -19 837 737 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N odieresis ; B 83 -14 585 706 ;
+C -1 ; WX 556 ; N oacute ; B 83 -14 587 734 ;
+C -1 ; WX 400 ; N degree ; B 169 411 468 703 ;
+C -1 ; WX 278 ; N igrave ; B 95 0 310 734 ;
+C -1 ; WX 556 ; N mu ; B 24 -207 600 523 ;
+C -1 ; WX 778 ; N Oacute ; B 105 -19 826 929 ;
+C -1 ; WX 556 ; N eth ; B 81 -15 617 737 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 667 ; N Yacute ; B 167 0 806 929 ;
+C -1 ; WX 260 ; N brokenbar ; B 90 -19 324 737 ;
+C -1 ; WX 834 ; N onehalf ; B 114 -19 839 703 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 250
+
+KPX A y -40
+KPX A w -40
+KPX A v -40
+KPX A u -30
+KPX A Y -100
+KPX A W -50
+KPX A V -70
+KPX A U -50
+KPX A T -120
+KPX A Q -30
+KPX A O -30
+KPX A G -30
+KPX A C -30
+
+KPX B period -20
+KPX B comma -20
+KPX B U -10
+
+KPX C period -30
+KPX C comma -30
+
+KPX D period -70
+KPX D comma -70
+KPX D Y -90
+KPX D W -40
+KPX D V -70
+KPX D A -40
+
+KPX F r -45
+KPX F period -150
+KPX F o -30
+KPX F e -30
+KPX F comma -150
+KPX F a -50
+KPX F A -80
+
+KPX J u -20
+KPX J period -30
+KPX J comma -30
+KPX J a -20
+KPX J A -20
+
+KPX K y -50
+KPX K u -30
+KPX K o -40
+KPX K e -40
+KPX K O -50
+
+KPX L y -30
+KPX L quoteright -160
+KPX L quotedblright -140
+KPX L Y -140
+KPX L W -70
+KPX L V -110
+KPX L T -110
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -60
+KPX O W -30
+KPX O V -50
+KPX O T -40
+KPX O A -20
+
+KPX P period -180
+KPX P o -50
+KPX P e -50
+KPX P comma -180
+KPX P a -40
+KPX P A -120
+
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -30
+KPX R V -50
+KPX R U -40
+KPX R T -30
+KPX R O -20
+
+KPX S period -20
+KPX S comma -20
+
+KPX T y -120
+KPX T w -120
+KPX T u -120
+KPX T semicolon -20
+KPX T r -120
+KPX T period -120
+KPX T o -120
+KPX T hyphen -140
+KPX T e -120
+KPX T comma -120
+KPX T colon -20
+KPX T a -120
+KPX T O -40
+KPX T A -120
+
+KPX U period -40
+KPX U comma -40
+KPX U A -40
+
+KPX V u -70
+KPX V semicolon -40
+KPX V period -125
+KPX V o -80
+KPX V hyphen -80
+KPX V e -80
+KPX V comma -125
+KPX V colon -40
+KPX V a -70
+KPX V O -40
+KPX V G -40
+KPX V A -80
+
+KPX W y -20
+KPX W u -30
+KPX W period -80
+KPX W o -30
+KPX W hyphen -40
+KPX W e -30
+KPX W comma -80
+KPX W a -40
+KPX W O -20
+KPX W A -50
+
+KPX Y u -110
+KPX Y semicolon -60
+KPX Y period -140
+KPX Y o -140
+KPX Y i -20
+KPX Y hyphen -140
+KPX Y e -140
+KPX Y comma -140
+KPX Y colon -60
+KPX Y a -140
+KPX Y O -85
+KPX Y A -110
+
+KPX a y -30
+KPX a w -20
+KPX a v -20
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b period -40
+KPX b l -20
+KPX b comma -40
+KPX b b -10
+
+KPX c k -20
+KPX c comma -15
+
+KPX colon space -50
+
+KPX comma quoteright -100
+KPX comma quotedblright -100
+
+KPX e y -20
+KPX e x -30
+KPX e w -20
+KPX e v -30
+KPX e period -15
+KPX e comma -15
+
+KPX f quoteright 50
+KPX f quotedblright 60
+KPX f period -30
+KPX f o -30
+KPX f e -30
+KPX f dotlessi -28
+KPX f comma -30
+KPX f a -30
+
+KPX g r -10
+
+KPX h y -30
+
+KPX k o -20
+KPX k e -20
+
+KPX m y -15
+KPX m u -10
+
+KPX n y -15
+KPX n v -20
+KPX n u -10
+
+KPX o y -30
+KPX o x -30
+KPX o w -15
+KPX o v -15
+KPX o period -40
+KPX o comma -40
+
+KPX oslash z -55
+KPX oslash y -70
+KPX oslash x -85
+KPX oslash w -70
+KPX oslash v -70
+KPX oslash u -55
+KPX oslash t -55
+KPX oslash s -55
+KPX oslash r -55
+KPX oslash q -55
+KPX oslash period -95
+KPX oslash p -55
+KPX oslash o -55
+KPX oslash n -55
+KPX oslash m -55
+KPX oslash l -55
+KPX oslash k -55
+KPX oslash j -55
+KPX oslash i -55
+KPX oslash h -55
+KPX oslash g -55
+KPX oslash f -55
+KPX oslash e -55
+KPX oslash d -55
+KPX oslash comma -95
+KPX oslash c -55
+KPX oslash b -55
+KPX oslash a -55
+
+KPX p y -30
+KPX p period -35
+KPX p comma -35
+
+KPX period space -60
+KPX period quoteright -100
+KPX period quotedblright -100
+
+KPX quotedblright space -40
+
+KPX quoteleft quoteleft -57
+
+KPX quoteright space -70
+KPX quoteright s -50
+KPX quoteright r -50
+KPX quoteright quoteright -57
+KPX quoteright d -50
+
+KPX r y 30
+KPX r v 30
+KPX r u 15
+KPX r t 40
+KPX r semicolon 30
+KPX r period -50
+KPX r p 30
+KPX r n 25
+KPX r m 25
+KPX r l 15
+KPX r k 15
+KPX r i 15
+KPX r comma -50
+KPX r colon 30
+KPX r a -10
+
+KPX s w -30
+KPX s period -15
+KPX s comma -15
+
+KPX semicolon space -50
+
+KPX space quoteleft -60
+KPX space quotedblleft -30
+KPX space Y -90
+KPX space W -40
+KPX space V -50
+KPX space T -50
+
+KPX v period -80
+KPX v o -25
+KPX v e -25
+KPX v comma -80
+KPX v a -25
+
+KPX w period -60
+KPX w o -10
+KPX w e -10
+KPX w comma -60
+KPX w a -15
+
+KPX x e -30
+
+KPX y period -100
+KPX y o -20
+KPX y e -20
+KPX y comma -100
+KPX y a -20
+
+KPX z o -15
+KPX z e -15
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 208 195 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 208 195 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 208 195 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 208 195 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 204 175 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 208 195 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 195 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 208 195 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 208 195 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 208 195 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 208 195 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 14 195 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 14 195 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 14 195 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 14 195 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 246 195 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 264 195 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 264 195 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 264 195 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 264 195 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 264 195 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 208 195 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 236 195 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 236 195 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 236 195 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 236 195 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 208 195 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 208 195 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 180 195 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 102 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 84 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 102 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 112 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 112 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 112 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 84 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 112 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Helvetica.afm b/tlt3.0/library/afm/Helvetica.afm
new file mode 100644
index 0000000..80d8cff
--- /dev/null
+++ b/tlt3.0/library/afm/Helvetica.afm
@@ -0,0 +1,613 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Thu Mar 15 08:58:00 1990
+Comment UniqueID 28352
+Comment VMusage 26389 33281
+FontName Helvetica
+FullName Helvetica
+FamilyName Helvetica
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -166 -225 1000 931
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.Helvetica is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 718
+XHeight 523
+Ascender 718
+Descender -207
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 90 0 187 718 ;
+C 34 ; WX 355 ; N quotedbl ; B 70 463 285 718 ;
+C 35 ; WX 556 ; N numbersign ; B 28 0 529 688 ;
+C 36 ; WX 556 ; N dollar ; B 32 -115 520 775 ;
+C 37 ; WX 889 ; N percent ; B 39 -19 850 703 ;
+C 38 ; WX 667 ; N ampersand ; B 44 -15 645 718 ;
+C 39 ; WX 222 ; N quoteright ; B 53 463 157 718 ;
+C 40 ; WX 333 ; N parenleft ; B 68 -207 299 733 ;
+C 41 ; WX 333 ; N parenright ; B 34 -207 265 733 ;
+C 42 ; WX 389 ; N asterisk ; B 39 431 349 718 ;
+C 43 ; WX 584 ; N plus ; B 39 0 545 505 ;
+C 44 ; WX 278 ; N comma ; B 87 -147 191 106 ;
+C 45 ; WX 333 ; N hyphen ; B 44 232 289 322 ;
+C 46 ; WX 278 ; N period ; B 87 0 191 106 ;
+C 47 ; WX 278 ; N slash ; B -17 -19 295 737 ;
+C 48 ; WX 556 ; N zero ; B 37 -19 519 703 ;
+C 49 ; WX 556 ; N one ; B 101 0 359 703 ;
+C 50 ; WX 556 ; N two ; B 26 0 507 703 ;
+C 51 ; WX 556 ; N three ; B 34 -19 522 703 ;
+C 52 ; WX 556 ; N four ; B 25 0 523 703 ;
+C 53 ; WX 556 ; N five ; B 32 -19 514 688 ;
+C 54 ; WX 556 ; N six ; B 38 -19 518 703 ;
+C 55 ; WX 556 ; N seven ; B 37 0 523 688 ;
+C 56 ; WX 556 ; N eight ; B 38 -19 517 703 ;
+C 57 ; WX 556 ; N nine ; B 42 -19 514 703 ;
+C 58 ; WX 278 ; N colon ; B 87 0 191 516 ;
+C 59 ; WX 278 ; N semicolon ; B 87 -147 191 516 ;
+C 60 ; WX 584 ; N less ; B 48 11 536 495 ;
+C 61 ; WX 584 ; N equal ; B 39 115 545 390 ;
+C 62 ; WX 584 ; N greater ; B 48 11 536 495 ;
+C 63 ; WX 556 ; N question ; B 56 0 492 727 ;
+C 64 ; WX 1015 ; N at ; B 147 -19 868 737 ;
+C 65 ; WX 667 ; N A ; B 14 0 654 718 ;
+C 66 ; WX 667 ; N B ; B 74 0 627 718 ;
+C 67 ; WX 722 ; N C ; B 44 -19 681 737 ;
+C 68 ; WX 722 ; N D ; B 81 0 674 718 ;
+C 69 ; WX 667 ; N E ; B 86 0 616 718 ;
+C 70 ; WX 611 ; N F ; B 86 0 583 718 ;
+C 71 ; WX 778 ; N G ; B 48 -19 704 737 ;
+C 72 ; WX 722 ; N H ; B 77 0 646 718 ;
+C 73 ; WX 278 ; N I ; B 91 0 188 718 ;
+C 74 ; WX 500 ; N J ; B 17 -19 428 718 ;
+C 75 ; WX 667 ; N K ; B 76 0 663 718 ;
+C 76 ; WX 556 ; N L ; B 76 0 537 718 ;
+C 77 ; WX 833 ; N M ; B 73 0 761 718 ;
+C 78 ; WX 722 ; N N ; B 76 0 646 718 ;
+C 79 ; WX 778 ; N O ; B 39 -19 739 737 ;
+C 80 ; WX 667 ; N P ; B 86 0 622 718 ;
+C 81 ; WX 778 ; N Q ; B 39 -56 739 737 ;
+C 82 ; WX 722 ; N R ; B 88 0 684 718 ;
+C 83 ; WX 667 ; N S ; B 49 -19 620 737 ;
+C 84 ; WX 611 ; N T ; B 14 0 597 718 ;
+C 85 ; WX 722 ; N U ; B 79 -19 644 718 ;
+C 86 ; WX 667 ; N V ; B 20 0 647 718 ;
+C 87 ; WX 944 ; N W ; B 16 0 928 718 ;
+C 88 ; WX 667 ; N X ; B 19 0 648 718 ;
+C 89 ; WX 667 ; N Y ; B 14 0 653 718 ;
+C 90 ; WX 611 ; N Z ; B 23 0 588 718 ;
+C 91 ; WX 278 ; N bracketleft ; B 63 -196 250 722 ;
+C 92 ; WX 278 ; N backslash ; B -17 -19 295 737 ;
+C 93 ; WX 278 ; N bracketright ; B 28 -196 215 722 ;
+C 94 ; WX 469 ; N asciicircum ; B -14 264 483 688 ;
+C 95 ; WX 556 ; N underscore ; B 0 -125 556 -75 ;
+C 96 ; WX 222 ; N quoteleft ; B 65 470 169 725 ;
+C 97 ; WX 556 ; N a ; B 36 -15 530 538 ;
+C 98 ; WX 556 ; N b ; B 58 -15 517 718 ;
+C 99 ; WX 500 ; N c ; B 30 -15 477 538 ;
+C 100 ; WX 556 ; N d ; B 35 -15 499 718 ;
+C 101 ; WX 556 ; N e ; B 40 -15 516 538 ;
+C 102 ; WX 278 ; N f ; B 14 0 262 728 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 40 -220 499 538 ;
+C 104 ; WX 556 ; N h ; B 65 0 491 718 ;
+C 105 ; WX 222 ; N i ; B 67 0 155 718 ;
+C 106 ; WX 222 ; N j ; B -16 -210 155 718 ;
+C 107 ; WX 500 ; N k ; B 67 0 501 718 ;
+C 108 ; WX 222 ; N l ; B 67 0 155 718 ;
+C 109 ; WX 833 ; N m ; B 65 0 769 538 ;
+C 110 ; WX 556 ; N n ; B 65 0 491 538 ;
+C 111 ; WX 556 ; N o ; B 35 -14 521 538 ;
+C 112 ; WX 556 ; N p ; B 58 -207 517 538 ;
+C 113 ; WX 556 ; N q ; B 35 -207 494 538 ;
+C 114 ; WX 333 ; N r ; B 77 0 332 538 ;
+C 115 ; WX 500 ; N s ; B 32 -15 464 538 ;
+C 116 ; WX 278 ; N t ; B 14 -7 257 669 ;
+C 117 ; WX 556 ; N u ; B 68 -15 489 523 ;
+C 118 ; WX 500 ; N v ; B 8 0 492 523 ;
+C 119 ; WX 722 ; N w ; B 14 0 709 523 ;
+C 120 ; WX 500 ; N x ; B 11 0 490 523 ;
+C 121 ; WX 500 ; N y ; B 11 -214 489 523 ;
+C 122 ; WX 500 ; N z ; B 31 0 469 523 ;
+C 123 ; WX 334 ; N braceleft ; B 42 -196 292 722 ;
+C 124 ; WX 260 ; N bar ; B 94 -19 167 737 ;
+C 125 ; WX 334 ; N braceright ; B 42 -196 292 722 ;
+C 126 ; WX 584 ; N asciitilde ; B 61 180 523 326 ;
+C 161 ; WX 333 ; N exclamdown ; B 118 -195 215 523 ;
+C 162 ; WX 556 ; N cent ; B 51 -115 513 623 ;
+C 163 ; WX 556 ; N sterling ; B 33 -16 539 718 ;
+C 164 ; WX 167 ; N fraction ; B -166 -19 333 703 ;
+C 165 ; WX 556 ; N yen ; B 3 0 553 688 ;
+C 166 ; WX 556 ; N florin ; B -11 -207 501 737 ;
+C 167 ; WX 556 ; N section ; B 43 -191 512 737 ;
+C 168 ; WX 556 ; N currency ; B 28 99 528 603 ;
+C 169 ; WX 191 ; N quotesingle ; B 59 463 132 718 ;
+C 170 ; WX 333 ; N quotedblleft ; B 38 470 307 725 ;
+C 171 ; WX 556 ; N guillemotleft ; B 97 108 459 446 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 88 108 245 446 ;
+C 173 ; WX 333 ; N guilsinglright ; B 88 108 245 446 ;
+C 174 ; WX 500 ; N fi ; B 14 0 434 728 ;
+C 175 ; WX 500 ; N fl ; B 14 0 432 728 ;
+C 177 ; WX 556 ; N endash ; B 0 240 556 313 ;
+C 178 ; WX 556 ; N dagger ; B 43 -159 514 718 ;
+C 179 ; WX 556 ; N daggerdbl ; B 43 -159 514 718 ;
+C 180 ; WX 278 ; N periodcentered ; B 77 190 202 315 ;
+C 182 ; WX 537 ; N paragraph ; B 18 -173 497 718 ;
+C 183 ; WX 350 ; N bullet ; B 18 202 333 517 ;
+C 184 ; WX 222 ; N quotesinglbase ; B 53 -149 157 106 ;
+C 185 ; WX 333 ; N quotedblbase ; B 26 -149 295 106 ;
+C 186 ; WX 333 ; N quotedblright ; B 26 463 295 718 ;
+C 187 ; WX 556 ; N guillemotright ; B 97 108 459 446 ;
+C 188 ; WX 1000 ; N ellipsis ; B 115 0 885 106 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 703 ;
+C 191 ; WX 611 ; N questiondown ; B 91 -201 527 525 ;
+C 193 ; WX 333 ; N grave ; B 14 593 211 734 ;
+C 194 ; WX 333 ; N acute ; B 122 593 319 734 ;
+C 195 ; WX 333 ; N circumflex ; B 21 593 312 734 ;
+C 196 ; WX 333 ; N tilde ; B -4 606 337 722 ;
+C 197 ; WX 333 ; N macron ; B 10 627 323 684 ;
+C 198 ; WX 333 ; N breve ; B 13 595 321 731 ;
+C 199 ; WX 333 ; N dotaccent ; B 121 604 212 706 ;
+C 200 ; WX 333 ; N dieresis ; B 40 604 293 706 ;
+C 202 ; WX 333 ; N ring ; B 75 572 259 756 ;
+C 203 ; WX 333 ; N cedilla ; B 45 -225 259 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 31 593 409 734 ;
+C 206 ; WX 333 ; N ogonek ; B 73 -225 287 0 ;
+C 207 ; WX 333 ; N caron ; B 21 593 312 734 ;
+C 208 ; WX 1000 ; N emdash ; B 0 240 1000 313 ;
+C 225 ; WX 1000 ; N AE ; B 8 0 951 718 ;
+C 227 ; WX 370 ; N ordfeminine ; B 24 304 346 737 ;
+C 232 ; WX 556 ; N Lslash ; B -20 0 537 718 ;
+C 233 ; WX 778 ; N Oslash ; B 39 -19 740 737 ;
+C 234 ; WX 1000 ; N OE ; B 36 -19 965 737 ;
+C 235 ; WX 365 ; N ordmasculine ; B 25 304 341 737 ;
+C 241 ; WX 889 ; N ae ; B 36 -15 847 538 ;
+C 245 ; WX 278 ; N dotlessi ; B 95 0 183 523 ;
+C 248 ; WX 222 ; N lslash ; B -20 0 242 718 ;
+C 249 ; WX 611 ; N oslash ; B 28 -22 537 545 ;
+C 250 ; WX 944 ; N oe ; B 35 -15 902 538 ;
+C 251 ; WX 611 ; N germandbls ; B 67 -15 571 728 ;
+C -1 ; WX 611 ; N Zcaron ; B 23 0 588 929 ;
+C -1 ; WX 500 ; N ccedilla ; B 30 -225 477 538 ;
+C -1 ; WX 500 ; N ydieresis ; B 11 -214 489 706 ;
+C -1 ; WX 556 ; N atilde ; B 36 -15 530 722 ;
+C -1 ; WX 278 ; N icircumflex ; B -6 0 285 734 ;
+C -1 ; WX 333 ; N threesuperior ; B 5 270 325 703 ;
+C -1 ; WX 556 ; N ecircumflex ; B 40 -15 516 734 ;
+C -1 ; WX 556 ; N thorn ; B 58 -207 517 718 ;
+C -1 ; WX 556 ; N egrave ; B 40 -15 516 734 ;
+C -1 ; WX 333 ; N twosuperior ; B 4 281 323 703 ;
+C -1 ; WX 556 ; N eacute ; B 40 -15 516 734 ;
+C -1 ; WX 556 ; N otilde ; B 35 -14 521 722 ;
+C -1 ; WX 667 ; N Aacute ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N ocircumflex ; B 35 -14 521 734 ;
+C -1 ; WX 500 ; N yacute ; B 11 -214 489 734 ;
+C -1 ; WX 556 ; N udieresis ; B 68 -15 489 706 ;
+C -1 ; WX 834 ; N threequarters ; B 45 -19 810 703 ;
+C -1 ; WX 556 ; N acircumflex ; B 36 -15 530 734 ;
+C -1 ; WX 722 ; N Eth ; B 0 0 674 718 ;
+C -1 ; WX 556 ; N edieresis ; B 40 -15 516 706 ;
+C -1 ; WX 556 ; N ugrave ; B 68 -15 489 734 ;
+C -1 ; WX 1000 ; N trademark ; B 46 306 903 718 ;
+C -1 ; WX 556 ; N ograve ; B 35 -14 521 734 ;
+C -1 ; WX 500 ; N scaron ; B 32 -15 464 734 ;
+C -1 ; WX 278 ; N Idieresis ; B 13 0 266 901 ;
+C -1 ; WX 556 ; N uacute ; B 68 -15 489 734 ;
+C -1 ; WX 556 ; N agrave ; B 36 -15 530 734 ;
+C -1 ; WX 556 ; N ntilde ; B 65 0 491 722 ;
+C -1 ; WX 556 ; N aring ; B 36 -15 530 756 ;
+C -1 ; WX 500 ; N zcaron ; B 31 0 469 734 ;
+C -1 ; WX 278 ; N Icircumflex ; B -6 0 285 929 ;
+C -1 ; WX 722 ; N Ntilde ; B 76 0 646 917 ;
+C -1 ; WX 556 ; N ucircumflex ; B 68 -15 489 734 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 86 0 616 929 ;
+C -1 ; WX 278 ; N Iacute ; B 91 0 292 929 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -225 681 737 ;
+C -1 ; WX 778 ; N Odieresis ; B 39 -19 739 901 ;
+C -1 ; WX 667 ; N Scaron ; B 49 -19 620 929 ;
+C -1 ; WX 667 ; N Edieresis ; B 86 0 616 901 ;
+C -1 ; WX 278 ; N Igrave ; B -13 0 188 929 ;
+C -1 ; WX 556 ; N adieresis ; B 36 -15 530 706 ;
+C -1 ; WX 778 ; N Ograve ; B 39 -19 739 929 ;
+C -1 ; WX 667 ; N Egrave ; B 86 0 616 929 ;
+C -1 ; WX 667 ; N Ydieresis ; B 14 0 653 901 ;
+C -1 ; WX 737 ; N registered ; B -14 -19 752 737 ;
+C -1 ; WX 778 ; N Otilde ; B 39 -19 739 917 ;
+C -1 ; WX 834 ; N onequarter ; B 73 -19 756 703 ;
+C -1 ; WX 722 ; N Ugrave ; B 79 -19 644 929 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 79 -19 644 929 ;
+C -1 ; WX 667 ; N Thorn ; B 86 0 622 718 ;
+C -1 ; WX 584 ; N divide ; B 39 -19 545 524 ;
+C -1 ; WX 667 ; N Atilde ; B 14 0 654 917 ;
+C -1 ; WX 722 ; N Uacute ; B 79 -19 644 929 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 39 -19 739 929 ;
+C -1 ; WX 584 ; N logicalnot ; B 39 108 545 390 ;
+C -1 ; WX 667 ; N Aring ; B 14 0 654 931 ;
+C -1 ; WX 278 ; N idieresis ; B 13 0 266 706 ;
+C -1 ; WX 278 ; N iacute ; B 95 0 292 734 ;
+C -1 ; WX 556 ; N aacute ; B 36 -15 530 734 ;
+C -1 ; WX 584 ; N plusminus ; B 39 0 545 506 ;
+C -1 ; WX 584 ; N multiply ; B 39 0 545 506 ;
+C -1 ; WX 722 ; N Udieresis ; B 79 -19 644 901 ;
+C -1 ; WX 584 ; N minus ; B 39 216 545 289 ;
+C -1 ; WX 333 ; N onesuperior ; B 43 281 222 703 ;
+C -1 ; WX 667 ; N Eacute ; B 86 0 616 929 ;
+C -1 ; WX 667 ; N Acircumflex ; B 14 0 654 929 ;
+C -1 ; WX 737 ; N copyright ; B -14 -19 752 737 ;
+C -1 ; WX 667 ; N Agrave ; B 14 0 654 929 ;
+C -1 ; WX 556 ; N odieresis ; B 35 -14 521 706 ;
+C -1 ; WX 556 ; N oacute ; B 35 -14 521 734 ;
+C -1 ; WX 400 ; N degree ; B 54 411 346 703 ;
+C -1 ; WX 278 ; N igrave ; B -13 0 184 734 ;
+C -1 ; WX 556 ; N mu ; B 68 -207 489 523 ;
+C -1 ; WX 778 ; N Oacute ; B 39 -19 739 929 ;
+C -1 ; WX 556 ; N eth ; B 35 -15 522 737 ;
+C -1 ; WX 667 ; N Adieresis ; B 14 0 654 901 ;
+C -1 ; WX 667 ; N Yacute ; B 14 0 653 929 ;
+C -1 ; WX 260 ; N brokenbar ; B 94 -19 167 737 ;
+C -1 ; WX 834 ; N onehalf ; B 43 -19 773 703 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 250
+
+KPX A y -40
+KPX A w -40
+KPX A v -40
+KPX A u -30
+KPX A Y -100
+KPX A W -50
+KPX A V -70
+KPX A U -50
+KPX A T -120
+KPX A Q -30
+KPX A O -30
+KPX A G -30
+KPX A C -30
+
+KPX B period -20
+KPX B comma -20
+KPX B U -10
+
+KPX C period -30
+KPX C comma -30
+
+KPX D period -70
+KPX D comma -70
+KPX D Y -90
+KPX D W -40
+KPX D V -70
+KPX D A -40
+
+KPX F r -45
+KPX F period -150
+KPX F o -30
+KPX F e -30
+KPX F comma -150
+KPX F a -50
+KPX F A -80
+
+KPX J u -20
+KPX J period -30
+KPX J comma -30
+KPX J a -20
+KPX J A -20
+
+KPX K y -50
+KPX K u -30
+KPX K o -40
+KPX K e -40
+KPX K O -50
+
+KPX L y -30
+KPX L quoteright -160
+KPX L quotedblright -140
+KPX L Y -140
+KPX L W -70
+KPX L V -110
+KPX L T -110
+
+KPX O period -40
+KPX O comma -40
+KPX O Y -70
+KPX O X -60
+KPX O W -30
+KPX O V -50
+KPX O T -40
+KPX O A -20
+
+KPX P period -180
+KPX P o -50
+KPX P e -50
+KPX P comma -180
+KPX P a -40
+KPX P A -120
+
+KPX Q U -10
+
+KPX R Y -50
+KPX R W -30
+KPX R V -50
+KPX R U -40
+KPX R T -30
+KPX R O -20
+
+KPX S period -20
+KPX S comma -20
+
+KPX T y -120
+KPX T w -120
+KPX T u -120
+KPX T semicolon -20
+KPX T r -120
+KPX T period -120
+KPX T o -120
+KPX T hyphen -140
+KPX T e -120
+KPX T comma -120
+KPX T colon -20
+KPX T a -120
+KPX T O -40
+KPX T A -120
+
+KPX U period -40
+KPX U comma -40
+KPX U A -40
+
+KPX V u -70
+KPX V semicolon -40
+KPX V period -125
+KPX V o -80
+KPX V hyphen -80
+KPX V e -80
+KPX V comma -125
+KPX V colon -40
+KPX V a -70
+KPX V O -40
+KPX V G -40
+KPX V A -80
+
+KPX W y -20
+KPX W u -30
+KPX W period -80
+KPX W o -30
+KPX W hyphen -40
+KPX W e -30
+KPX W comma -80
+KPX W a -40
+KPX W O -20
+KPX W A -50
+
+KPX Y u -110
+KPX Y semicolon -60
+KPX Y period -140
+KPX Y o -140
+KPX Y i -20
+KPX Y hyphen -140
+KPX Y e -140
+KPX Y comma -140
+KPX Y colon -60
+KPX Y a -140
+KPX Y O -85
+KPX Y A -110
+
+KPX a y -30
+KPX a w -20
+KPX a v -20
+
+KPX b y -20
+KPX b v -20
+KPX b u -20
+KPX b period -40
+KPX b l -20
+KPX b comma -40
+KPX b b -10
+
+KPX c k -20
+KPX c comma -15
+
+KPX colon space -50
+
+KPX comma quoteright -100
+KPX comma quotedblright -100
+
+KPX e y -20
+KPX e x -30
+KPX e w -20
+KPX e v -30
+KPX e period -15
+KPX e comma -15
+
+KPX f quoteright 50
+KPX f quotedblright 60
+KPX f period -30
+KPX f o -30
+KPX f e -30
+KPX f dotlessi -28
+KPX f comma -30
+KPX f a -30
+
+KPX g r -10
+
+KPX h y -30
+
+KPX k o -20
+KPX k e -20
+
+KPX m y -15
+KPX m u -10
+
+KPX n y -15
+KPX n v -20
+KPX n u -10
+
+KPX o y -30
+KPX o x -30
+KPX o w -15
+KPX o v -15
+KPX o period -40
+KPX o comma -40
+
+KPX oslash z -55
+KPX oslash y -70
+KPX oslash x -85
+KPX oslash w -70
+KPX oslash v -70
+KPX oslash u -55
+KPX oslash t -55
+KPX oslash s -55
+KPX oslash r -55
+KPX oslash q -55
+KPX oslash period -95
+KPX oslash p -55
+KPX oslash o -55
+KPX oslash n -55
+KPX oslash m -55
+KPX oslash l -55
+KPX oslash k -55
+KPX oslash j -55
+KPX oslash i -55
+KPX oslash h -55
+KPX oslash g -55
+KPX oslash f -55
+KPX oslash e -55
+KPX oslash d -55
+KPX oslash comma -95
+KPX oslash c -55
+KPX oslash b -55
+KPX oslash a -55
+
+KPX p y -30
+KPX p period -35
+KPX p comma -35
+
+KPX period space -60
+KPX period quoteright -100
+KPX period quotedblright -100
+
+KPX quotedblright space -40
+
+KPX quoteleft quoteleft -57
+
+KPX quoteright space -70
+KPX quoteright s -50
+KPX quoteright r -50
+KPX quoteright quoteright -57
+KPX quoteright d -50
+
+KPX r y 30
+KPX r v 30
+KPX r u 15
+KPX r t 40
+KPX r semicolon 30
+KPX r period -50
+KPX r p 30
+KPX r n 25
+KPX r m 25
+KPX r l 15
+KPX r k 15
+KPX r i 15
+KPX r comma -50
+KPX r colon 30
+KPX r a -10
+
+KPX s w -30
+KPX s period -15
+KPX s comma -15
+
+KPX semicolon space -50
+
+KPX space quoteleft -60
+KPX space quotedblleft -30
+KPX space Y -90
+KPX space W -40
+KPX space V -50
+KPX space T -50
+
+KPX v period -80
+KPX v o -25
+KPX v e -25
+KPX v comma -80
+KPX v a -25
+
+KPX w period -60
+KPX w o -10
+KPX w e -10
+KPX w comma -60
+KPX w a -15
+
+KPX x e -30
+
+KPX y period -100
+KPX y o -20
+KPX y e -20
+KPX y comma -100
+KPX y a -20
+
+KPX z o -15
+KPX z e -15
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 167 195 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 167 195 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 167 195 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 167 195 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 167 175 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 167 195 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 195 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 167 195 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 167 195 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 167 195 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 167 195 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute -27 195 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex -27 195 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis -27 195 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave -27 195 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 205 195 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 195 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 195 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 195 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 195 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 195 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 167 195 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 195 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 195 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 195 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 195 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 167 195 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 167 195 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 195 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 112 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 102 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 84 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 112 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 112 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 112 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 112 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 102 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 112 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 112 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 112 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 84 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 112 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/NewCenturySchlbk-Bold.afm b/tlt3.0/library/afm/NewCenturySchlbk-Bold.afm
new file mode 100644
index 0000000..6438f86
--- /dev/null
+++ b/tlt3.0/library/afm/NewCenturySchlbk-Bold.afm
@@ -0,0 +1,473 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1988, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue May 28 16:48:12 1991
+Comment UniqueID 35031
+Comment VMusage 30773 37665
+FontName NewCenturySchlbk-Bold
+FullName New Century Schoolbook Bold
+FamilyName New Century Schoolbook
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -165 -250 1000 988
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.009
+Notice Copyright (c) 1985, 1987, 1988, 1991 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 722
+XHeight 475
+Ascender 737
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 287 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 296 ; N exclam ; B 53 -15 243 737 ;
+C 34 ; WX 333 ; N quotedbl ; B 0 378 333 737 ;
+C 35 ; WX 574 ; N numbersign ; B 36 0 538 690 ;
+C 36 ; WX 574 ; N dollar ; B 25 -141 549 810 ;
+C 37 ; WX 833 ; N percent ; B 14 -15 819 705 ;
+C 38 ; WX 852 ; N ampersand ; B 34 -15 818 737 ;
+C 39 ; WX 241 ; N quoteright ; B 22 378 220 737 ;
+C 40 ; WX 389 ; N parenleft ; B 77 -117 345 745 ;
+C 41 ; WX 389 ; N parenright ; B 44 -117 312 745 ;
+C 42 ; WX 500 ; N asterisk ; B 54 302 446 737 ;
+C 43 ; WX 606 ; N plus ; B 50 0 556 506 ;
+C 44 ; WX 278 ; N comma ; B 40 -184 238 175 ;
+C 45 ; WX 333 ; N hyphen ; B 42 174 291 302 ;
+C 46 ; WX 278 ; N period ; B 44 -15 234 175 ;
+C 47 ; WX 278 ; N slash ; B -42 -15 320 737 ;
+C 48 ; WX 574 ; N zero ; B 27 -15 547 705 ;
+C 49 ; WX 574 ; N one ; B 83 0 491 705 ;
+C 50 ; WX 574 ; N two ; B 19 0 531 705 ;
+C 51 ; WX 574 ; N three ; B 23 -15 531 705 ;
+C 52 ; WX 574 ; N four ; B 19 0 547 705 ;
+C 53 ; WX 574 ; N five ; B 32 -15 534 705 ;
+C 54 ; WX 574 ; N six ; B 27 -15 547 705 ;
+C 55 ; WX 574 ; N seven ; B 45 -15 547 705 ;
+C 56 ; WX 574 ; N eight ; B 27 -15 548 705 ;
+C 57 ; WX 574 ; N nine ; B 27 -15 547 705 ;
+C 58 ; WX 278 ; N colon ; B 44 -15 234 485 ;
+C 59 ; WX 278 ; N semicolon ; B 40 -184 238 485 ;
+C 60 ; WX 606 ; N less ; B 50 -9 556 515 ;
+C 61 ; WX 606 ; N equal ; B 50 103 556 403 ;
+C 62 ; WX 606 ; N greater ; B 50 -9 556 515 ;
+C 63 ; WX 500 ; N question ; B 23 -15 477 737 ;
+C 64 ; WX 747 ; N at ; B -2 -15 750 737 ;
+C 65 ; WX 759 ; N A ; B -19 0 778 737 ;
+C 66 ; WX 778 ; N B ; B 19 0 739 722 ;
+C 67 ; WX 778 ; N C ; B 39 -15 723 737 ;
+C 68 ; WX 833 ; N D ; B 19 0 794 722 ;
+C 69 ; WX 759 ; N E ; B 19 0 708 722 ;
+C 70 ; WX 722 ; N F ; B 19 0 697 722 ;
+C 71 ; WX 833 ; N G ; B 39 -15 818 737 ;
+C 72 ; WX 870 ; N H ; B 19 0 851 722 ;
+C 73 ; WX 444 ; N I ; B 29 0 415 722 ;
+C 74 ; WX 648 ; N J ; B 6 -15 642 722 ;
+C 75 ; WX 815 ; N K ; B 19 0 822 722 ;
+C 76 ; WX 722 ; N L ; B 19 0 703 722 ;
+C 77 ; WX 981 ; N M ; B 10 0 971 722 ;
+C 78 ; WX 833 ; N N ; B 5 -10 828 722 ;
+C 79 ; WX 833 ; N O ; B 39 -15 794 737 ;
+C 80 ; WX 759 ; N P ; B 24 0 735 722 ;
+C 81 ; WX 833 ; N Q ; B 39 -189 808 737 ;
+C 82 ; WX 815 ; N R ; B 19 -15 815 722 ;
+C 83 ; WX 667 ; N S ; B 51 -15 634 737 ;
+C 84 ; WX 722 ; N T ; B 16 0 706 722 ;
+C 85 ; WX 833 ; N U ; B 14 -15 825 722 ;
+C 86 ; WX 759 ; N V ; B -19 -10 778 722 ;
+C 87 ; WX 981 ; N W ; B 7 -10 974 722 ;
+C 88 ; WX 722 ; N X ; B -12 0 734 722 ;
+C 89 ; WX 722 ; N Y ; B -12 0 734 722 ;
+C 90 ; WX 667 ; N Z ; B 28 0 639 722 ;
+C 91 ; WX 389 ; N bracketleft ; B 84 -109 339 737 ;
+C 92 ; WX 606 ; N backslash ; B 122 -15 484 737 ;
+C 93 ; WX 389 ; N bracketright ; B 50 -109 305 737 ;
+C 94 ; WX 606 ; N asciicircum ; B 66 325 540 690 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 241 ; N quoteleft ; B 22 378 220 737 ;
+C 97 ; WX 611 ; N a ; B 40 -15 601 485 ;
+C 98 ; WX 648 ; N b ; B 4 -15 616 737 ;
+C 99 ; WX 556 ; N c ; B 32 -15 524 485 ;
+C 100 ; WX 667 ; N d ; B 32 -15 644 737 ;
+C 101 ; WX 574 ; N e ; B 32 -15 542 485 ;
+C 102 ; WX 389 ; N f ; B 11 0 461 737 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B 30 -205 623 535 ;
+C 104 ; WX 685 ; N h ; B 17 0 662 737 ;
+C 105 ; WX 370 ; N i ; B 26 0 338 737 ;
+C 106 ; WX 352 ; N j ; B -86 -205 271 737 ;
+C 107 ; WX 667 ; N k ; B 17 0 662 737 ;
+C 108 ; WX 352 ; N l ; B 17 0 329 737 ;
+C 109 ; WX 963 ; N m ; B 17 0 940 485 ;
+C 110 ; WX 685 ; N n ; B 17 0 662 485 ;
+C 111 ; WX 611 ; N o ; B 32 -15 579 485 ;
+C 112 ; WX 667 ; N p ; B 17 -205 629 485 ;
+C 113 ; WX 648 ; N q ; B 32 -205 638 485 ;
+C 114 ; WX 519 ; N r ; B 17 0 516 485 ;
+C 115 ; WX 500 ; N s ; B 48 -15 476 485 ;
+C 116 ; WX 426 ; N t ; B 21 -15 405 675 ;
+C 117 ; WX 685 ; N u ; B 17 -15 668 475 ;
+C 118 ; WX 611 ; N v ; B 12 -10 599 475 ;
+C 119 ; WX 889 ; N w ; B 16 -10 873 475 ;
+C 120 ; WX 611 ; N x ; B 12 0 599 475 ;
+C 121 ; WX 611 ; N y ; B 12 -205 599 475 ;
+C 122 ; WX 537 ; N z ; B 38 0 499 475 ;
+C 123 ; WX 389 ; N braceleft ; B 36 -109 313 737 ;
+C 124 ; WX 606 ; N bar ; B 249 -250 357 750 ;
+C 125 ; WX 389 ; N braceright ; B 76 -109 353 737 ;
+C 126 ; WX 606 ; N asciitilde ; B 72 160 534 346 ;
+C 161 ; WX 296 ; N exclamdown ; B 53 -205 243 547 ;
+C 162 ; WX 574 ; N cent ; B 32 -102 528 572 ;
+C 163 ; WX 574 ; N sterling ; B 16 -15 558 705 ;
+C 164 ; WX 167 ; N fraction ; B -165 -15 332 705 ;
+C 165 ; WX 574 ; N yen ; B -10 0 584 690 ;
+C 166 ; WX 574 ; N florin ; B 14 -205 548 737 ;
+C 167 ; WX 500 ; N section ; B 62 -86 438 737 ;
+C 168 ; WX 574 ; N currency ; B 27 84 547 605 ;
+C 169 ; WX 241 ; N quotesingle ; B 53 378 189 737 ;
+C 170 ; WX 481 ; N quotedblleft ; B 22 378 459 737 ;
+C 171 ; WX 500 ; N guillemotleft ; B 46 79 454 397 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 62 79 271 397 ;
+C 173 ; WX 333 ; N guilsinglright ; B 62 79 271 397 ;
+C 174 ; WX 685 ; N fi ; B 11 0 666 737 ;
+C 175 ; WX 685 ; N fl ; B 11 0 666 737 ;
+C 177 ; WX 500 ; N endash ; B 0 184 500 292 ;
+C 178 ; WX 500 ; N dagger ; B 39 -101 461 737 ;
+C 179 ; WX 500 ; N daggerdbl ; B 39 -89 461 737 ;
+C 180 ; WX 278 ; N periodcentered ; B 53 200 225 372 ;
+C 182 ; WX 747 ; N paragraph ; B 96 -71 631 722 ;
+C 183 ; WX 606 ; N bullet ; B 122 180 484 542 ;
+C 184 ; WX 241 ; N quotesinglbase ; B 22 -184 220 175 ;
+C 185 ; WX 481 ; N quotedblbase ; B 22 -184 459 175 ;
+C 186 ; WX 481 ; N quotedblright ; B 22 378 459 737 ;
+C 187 ; WX 500 ; N guillemotright ; B 46 79 454 397 ;
+C 188 ; WX 1000 ; N ellipsis ; B 72 -15 928 175 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -15 993 705 ;
+C 191 ; WX 500 ; N questiondown ; B 23 -205 477 547 ;
+C 193 ; WX 333 ; N grave ; B 2 547 249 737 ;
+C 194 ; WX 333 ; N acute ; B 84 547 331 737 ;
+C 195 ; WX 333 ; N circumflex ; B -10 547 344 725 ;
+C 196 ; WX 333 ; N tilde ; B -24 563 357 705 ;
+C 197 ; WX 333 ; N macron ; B -6 582 339 664 ;
+C 198 ; WX 333 ; N breve ; B 9 547 324 714 ;
+C 199 ; WX 333 ; N dotaccent ; B 95 552 237 694 ;
+C 200 ; WX 333 ; N dieresis ; B -12 552 345 694 ;
+C 202 ; WX 333 ; N ring ; B 58 545 274 761 ;
+C 203 ; WX 333 ; N cedilla ; B 17 -224 248 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -16 547 431 737 ;
+C 206 ; WX 333 ; N ogonek ; B 168 -163 346 3 ;
+C 207 ; WX 333 ; N caron ; B -10 547 344 725 ;
+C 208 ; WX 1000 ; N emdash ; B 0 184 1000 292 ;
+C 225 ; WX 981 ; N AE ; B -29 0 963 722 ;
+C 227 ; WX 367 ; N ordfeminine ; B 1 407 393 705 ;
+C 232 ; WX 722 ; N Lslash ; B 19 0 703 722 ;
+C 233 ; WX 833 ; N Oslash ; B 39 -53 794 775 ;
+C 234 ; WX 1000 ; N OE ; B 0 0 982 722 ;
+C 235 ; WX 367 ; N ordmasculine ; B 1 407 366 705 ;
+C 241 ; WX 870 ; N ae ; B 32 -15 838 485 ;
+C 245 ; WX 370 ; N dotlessi ; B 26 0 338 475 ;
+C 248 ; WX 352 ; N lslash ; B 17 0 329 737 ;
+C 249 ; WX 611 ; N oslash ; B 32 -103 579 573 ;
+C 250 ; WX 907 ; N oe ; B 32 -15 875 485 ;
+C 251 ; WX 611 ; N germandbls ; B -2 -15 580 737 ;
+C -1 ; WX 574 ; N ecircumflex ; B 32 -15 542 725 ;
+C -1 ; WX 574 ; N edieresis ; B 32 -15 542 694 ;
+C -1 ; WX 611 ; N aacute ; B 40 -15 601 737 ;
+C -1 ; WX 747 ; N registered ; B -2 -15 750 737 ;
+C -1 ; WX 370 ; N icircumflex ; B 9 0 363 725 ;
+C -1 ; WX 685 ; N udieresis ; B 17 -15 668 694 ;
+C -1 ; WX 611 ; N ograve ; B 32 -15 579 737 ;
+C -1 ; WX 685 ; N uacute ; B 17 -15 668 737 ;
+C -1 ; WX 685 ; N ucircumflex ; B 17 -15 668 725 ;
+C -1 ; WX 759 ; N Aacute ; B -19 0 778 964 ;
+C -1 ; WX 370 ; N igrave ; B 21 0 338 737 ;
+C -1 ; WX 444 ; N Icircumflex ; B 29 0 415 952 ;
+C -1 ; WX 556 ; N ccedilla ; B 32 -224 524 485 ;
+C -1 ; WX 611 ; N adieresis ; B 40 -15 601 694 ;
+C -1 ; WX 759 ; N Ecircumflex ; B 19 0 708 952 ;
+C -1 ; WX 500 ; N scaron ; B 48 -15 476 725 ;
+C -1 ; WX 667 ; N thorn ; B 17 -205 629 737 ;
+C -1 ; WX 1000 ; N trademark ; B 6 317 982 722 ;
+C -1 ; WX 574 ; N egrave ; B 32 -15 542 737 ;
+C -1 ; WX 344 ; N threesuperior ; B -3 273 355 705 ;
+C -1 ; WX 537 ; N zcaron ; B 38 0 499 725 ;
+C -1 ; WX 611 ; N atilde ; B 40 -15 601 705 ;
+C -1 ; WX 611 ; N aring ; B 40 -15 601 761 ;
+C -1 ; WX 611 ; N ocircumflex ; B 32 -15 579 725 ;
+C -1 ; WX 759 ; N Edieresis ; B 19 0 708 921 ;
+C -1 ; WX 861 ; N threequarters ; B 15 -15 838 705 ;
+C -1 ; WX 611 ; N ydieresis ; B 12 -205 599 694 ;
+C -1 ; WX 611 ; N yacute ; B 12 -205 599 737 ;
+C -1 ; WX 370 ; N iacute ; B 26 0 350 737 ;
+C -1 ; WX 759 ; N Acircumflex ; B -19 0 778 952 ;
+C -1 ; WX 833 ; N Uacute ; B 14 -15 825 964 ;
+C -1 ; WX 574 ; N eacute ; B 32 -15 542 737 ;
+C -1 ; WX 833 ; N Ograve ; B 39 -15 794 964 ;
+C -1 ; WX 611 ; N agrave ; B 40 -15 601 737 ;
+C -1 ; WX 833 ; N Udieresis ; B 14 -15 825 921 ;
+C -1 ; WX 611 ; N acircumflex ; B 40 -15 601 725 ;
+C -1 ; WX 444 ; N Igrave ; B 29 0 415 964 ;
+C -1 ; WX 344 ; N twosuperior ; B -3 282 350 705 ;
+C -1 ; WX 833 ; N Ugrave ; B 14 -15 825 964 ;
+C -1 ; WX 861 ; N onequarter ; B 31 -15 838 705 ;
+C -1 ; WX 833 ; N Ucircumflex ; B 14 -15 825 952 ;
+C -1 ; WX 667 ; N Scaron ; B 51 -15 634 952 ;
+C -1 ; WX 444 ; N Idieresis ; B 29 0 415 921 ;
+C -1 ; WX 370 ; N idieresis ; B 7 0 364 694 ;
+C -1 ; WX 759 ; N Egrave ; B 19 0 708 964 ;
+C -1 ; WX 833 ; N Oacute ; B 39 -15 794 964 ;
+C -1 ; WX 606 ; N divide ; B 50 -40 556 546 ;
+C -1 ; WX 759 ; N Atilde ; B -19 0 778 932 ;
+C -1 ; WX 759 ; N Aring ; B -19 0 778 988 ;
+C -1 ; WX 833 ; N Odieresis ; B 39 -15 794 921 ;
+C -1 ; WX 759 ; N Adieresis ; B -19 0 778 921 ;
+C -1 ; WX 833 ; N Ntilde ; B 5 -10 828 932 ;
+C -1 ; WX 667 ; N Zcaron ; B 28 0 639 952 ;
+C -1 ; WX 759 ; N Thorn ; B 24 0 735 722 ;
+C -1 ; WX 444 ; N Iacute ; B 29 0 415 964 ;
+C -1 ; WX 606 ; N plusminus ; B 50 0 556 506 ;
+C -1 ; WX 606 ; N multiply ; B 65 15 541 491 ;
+C -1 ; WX 759 ; N Eacute ; B 19 0 708 964 ;
+C -1 ; WX 722 ; N Ydieresis ; B -12 0 734 921 ;
+C -1 ; WX 344 ; N onesuperior ; B 31 282 309 705 ;
+C -1 ; WX 685 ; N ugrave ; B 17 -15 668 737 ;
+C -1 ; WX 606 ; N logicalnot ; B 50 103 556 403 ;
+C -1 ; WX 685 ; N ntilde ; B 17 0 662 705 ;
+C -1 ; WX 833 ; N Otilde ; B 39 -15 794 932 ;
+C -1 ; WX 611 ; N otilde ; B 32 -15 579 705 ;
+C -1 ; WX 778 ; N Ccedilla ; B 39 -224 723 737 ;
+C -1 ; WX 759 ; N Agrave ; B -19 0 778 964 ;
+C -1 ; WX 861 ; N onehalf ; B 31 -15 838 705 ;
+C -1 ; WX 833 ; N Eth ; B 19 0 794 722 ;
+C -1 ; WX 400 ; N degree ; B 57 419 343 705 ;
+C -1 ; WX 722 ; N Yacute ; B -12 0 734 964 ;
+C -1 ; WX 833 ; N Ocircumflex ; B 39 -15 794 952 ;
+C -1 ; WX 611 ; N oacute ; B 32 -15 579 737 ;
+C -1 ; WX 685 ; N mu ; B 17 -205 668 475 ;
+C -1 ; WX 606 ; N minus ; B 50 199 556 307 ;
+C -1 ; WX 611 ; N eth ; B 32 -15 579 737 ;
+C -1 ; WX 611 ; N odieresis ; B 32 -15 579 694 ;
+C -1 ; WX 747 ; N copyright ; B -2 -15 750 737 ;
+C -1 ; WX 606 ; N brokenbar ; B 249 -175 357 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 128
+
+KPX A y -18
+KPX A w -18
+KPX A v -18
+KPX A quoteright -74
+KPX A quotedblright -74
+KPX A Y -91
+KPX A W -74
+KPX A V -74
+KPX A U -18
+KPX A T -55
+
+KPX C period -18
+KPX C comma -18
+
+KPX D period -25
+KPX D comma -25
+
+KPX F r -18
+KPX F period -125
+KPX F o -55
+KPX F i -18
+KPX F e -55
+KPX F comma -125
+KPX F a -74
+
+KPX J u -18
+KPX J period -55
+KPX J o -18
+KPX J e -18
+KPX J comma -55
+KPX J a -18
+KPX J A -18
+
+KPX K y -25
+KPX K u -18
+
+KPX L y -25
+KPX L quoteright -100
+KPX L quotedblright -100
+KPX L Y -74
+KPX L W -74
+KPX L V -100
+KPX L T -100
+
+KPX N period -18
+KPX N comma -18
+
+KPX O period -25
+KPX O comma -25
+KPX O T 10
+
+KPX P period -150
+KPX P o -55
+KPX P e -55
+KPX P comma -150
+KPX P a -55
+KPX P A -74
+
+KPX S period -18
+KPX S comma -18
+
+KPX T u -18
+KPX T r -18
+KPX T period -100
+KPX T o -74
+KPX T i -18
+KPX T hyphen -125
+KPX T e -74
+KPX T comma -100
+KPX T a -74
+KPX T O 10
+KPX T A -55
+
+KPX U period -25
+KPX U comma -25
+KPX U A -18
+
+KPX V u -55
+KPX V semicolon -37
+KPX V period -125
+KPX V o -74
+KPX V i -18
+KPX V hyphen -100
+KPX V e -74
+KPX V comma -125
+KPX V colon -37
+KPX V a -74
+KPX V A -74
+
+KPX W y -25
+KPX W u -37
+KPX W semicolon -55
+KPX W period -100
+KPX W o -74
+KPX W i -18
+KPX W hyphen -100
+KPX W e -74
+KPX W comma -100
+KPX W colon -55
+KPX W a -74
+KPX W A -74
+
+KPX Y u -55
+KPX Y semicolon -25
+KPX Y period -100
+KPX Y o -100
+KPX Y i -18
+KPX Y hyphen -125
+KPX Y e -100
+KPX Y comma -100
+KPX Y colon -25
+KPX Y a -100
+KPX Y A -91
+
+KPX colon space -18
+
+KPX comma space -18
+KPX comma quoteright -18
+KPX comma quotedblright -18
+
+KPX f quoteright 75
+KPX f quotedblright 75
+
+KPX period space -18
+KPX period quoteright -18
+KPX period quotedblright -18
+
+KPX quotedblleft A -74
+
+KPX quotedblright space -18
+
+KPX quoteleft A -74
+
+KPX quoteright s -25
+KPX quoteright d -25
+
+KPX r period -74
+KPX r comma -74
+
+KPX semicolon space -18
+
+KPX space quoteleft -18
+KPX space quotedblleft -18
+KPX space Y -18
+KPX space W -18
+KPX space V -18
+KPX space T -18
+KPX space A -18
+
+KPX v period -100
+KPX v comma -100
+
+KPX w period -100
+KPX w comma -100
+
+KPX y period -100
+KPX y comma -100
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 213 227 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 213 227 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 213 227 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 213 227 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 213 227 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 213 227 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 213 227 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 213 227 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 213 227 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 213 227 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 56 227 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 56 227 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 56 227 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 56 227 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 250 227 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 250 227 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 250 227 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 250 227 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 250 227 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 250 227 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 167 227 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 250 227 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 250 227 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 250 227 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 250 227 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 195 227 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 195 227 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 167 227 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 139 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 139 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 139 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 139 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 139 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 139 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 121 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 121 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 121 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 121 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 19 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex 19 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis 19 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 19 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 176 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 139 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 139 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 139 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 139 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 139 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 84 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 176 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 176 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 176 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 176 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 139 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 139 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 102 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/NewCenturySchlbk-BoldItalic.afm b/tlt3.0/library/afm/NewCenturySchlbk-BoldItalic.afm
new file mode 100644
index 0000000..41611c7
--- /dev/null
+++ b/tlt3.0/library/afm/NewCenturySchlbk-BoldItalic.afm
@@ -0,0 +1,603 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue May 28 16:56:07 1991
+Comment UniqueID 35034
+Comment VMusage 31030 37922
+FontName NewCenturySchlbk-BoldItalic
+FullName New Century Schoolbook Bold Italic
+FamilyName New Century Schoolbook
+Weight Bold
+ItalicAngle -16
+IsFixedPitch false
+FontBBox -205 -250 1147 991
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 722
+XHeight 477
+Ascender 737
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 287 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 0 -15 333 737 ;
+C 34 ; WX 400 ; N quotedbl ; B 66 388 428 737 ;
+C 35 ; WX 574 ; N numbersign ; B 30 0 544 690 ;
+C 36 ; WX 574 ; N dollar ; B 9 -120 565 810 ;
+C 37 ; WX 889 ; N percent ; B 54 -28 835 727 ;
+C 38 ; WX 889 ; N ampersand ; B 32 -15 823 737 ;
+C 39 ; WX 259 ; N quoteright ; B 48 388 275 737 ;
+C 40 ; WX 407 ; N parenleft ; B 72 -117 454 745 ;
+C 41 ; WX 407 ; N parenright ; B -70 -117 310 745 ;
+C 42 ; WX 500 ; N asterisk ; B 58 301 498 737 ;
+C 43 ; WX 606 ; N plus ; B 50 0 556 506 ;
+C 44 ; WX 287 ; N comma ; B -57 -192 170 157 ;
+C 45 ; WX 333 ; N hyphen ; B 2 177 263 299 ;
+C 46 ; WX 287 ; N period ; B -20 -15 152 157 ;
+C 47 ; WX 278 ; N slash ; B -41 -15 320 737 ;
+C 48 ; WX 574 ; N zero ; B 21 -15 553 705 ;
+C 49 ; WX 574 ; N one ; B 25 0 489 705 ;
+C 50 ; WX 574 ; N two ; B -38 -3 538 705 ;
+C 51 ; WX 574 ; N three ; B -7 -15 536 705 ;
+C 52 ; WX 574 ; N four ; B -13 0 544 705 ;
+C 53 ; WX 574 ; N five ; B 0 -15 574 705 ;
+C 54 ; WX 574 ; N six ; B 31 -15 574 705 ;
+C 55 ; WX 574 ; N seven ; B 64 -15 593 705 ;
+C 56 ; WX 574 ; N eight ; B 0 -15 552 705 ;
+C 57 ; WX 574 ; N nine ; B 0 -15 543 705 ;
+C 58 ; WX 287 ; N colon ; B -20 -15 237 477 ;
+C 59 ; WX 287 ; N semicolon ; B -57 -192 237 477 ;
+C 60 ; WX 606 ; N less ; B 50 -9 556 515 ;
+C 61 ; WX 606 ; N equal ; B 50 103 556 403 ;
+C 62 ; WX 606 ; N greater ; B 50 -8 556 514 ;
+C 63 ; WX 481 ; N question ; B 79 -15 451 737 ;
+C 64 ; WX 747 ; N at ; B -4 -15 751 737 ;
+C 65 ; WX 741 ; N A ; B -75 0 716 737 ;
+C 66 ; WX 759 ; N B ; B -50 0 721 722 ;
+C 67 ; WX 759 ; N C ; B 37 -15 759 737 ;
+C 68 ; WX 833 ; N D ; B -47 0 796 722 ;
+C 69 ; WX 741 ; N E ; B -41 0 730 722 ;
+C 70 ; WX 704 ; N F ; B -41 0 730 722 ;
+C 71 ; WX 815 ; N G ; B 37 -15 805 737 ;
+C 72 ; WX 870 ; N H ; B -41 0 911 722 ;
+C 73 ; WX 444 ; N I ; B -41 0 485 722 ;
+C 74 ; WX 667 ; N J ; B -20 -15 708 722 ;
+C 75 ; WX 778 ; N K ; B -41 0 832 722 ;
+C 76 ; WX 704 ; N L ; B -41 0 670 722 ;
+C 77 ; WX 944 ; N M ; B -44 0 988 722 ;
+C 78 ; WX 852 ; N N ; B -61 -10 913 722 ;
+C 79 ; WX 833 ; N O ; B 37 -15 796 737 ;
+C 80 ; WX 741 ; N P ; B -41 0 730 722 ;
+C 81 ; WX 833 ; N Q ; B 37 -189 796 737 ;
+C 82 ; WX 796 ; N R ; B -41 -15 749 722 ;
+C 83 ; WX 685 ; N S ; B 1 -15 666 737 ;
+C 84 ; WX 722 ; N T ; B 41 0 759 722 ;
+C 85 ; WX 833 ; N U ; B 88 -15 900 722 ;
+C 86 ; WX 741 ; N V ; B 32 -10 802 722 ;
+C 87 ; WX 944 ; N W ; B 40 -10 1000 722 ;
+C 88 ; WX 741 ; N X ; B -82 0 801 722 ;
+C 89 ; WX 704 ; N Y ; B 13 0 775 722 ;
+C 90 ; WX 704 ; N Z ; B -33 0 711 722 ;
+C 91 ; WX 407 ; N bracketleft ; B 1 -109 464 737 ;
+C 92 ; WX 606 ; N backslash ; B 161 -15 445 737 ;
+C 93 ; WX 407 ; N bracketright ; B -101 -109 362 737 ;
+C 94 ; WX 606 ; N asciicircum ; B 66 325 540 690 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 259 ; N quoteleft ; B 47 388 274 737 ;
+C 97 ; WX 667 ; N a ; B 6 -15 636 477 ;
+C 98 ; WX 611 ; N b ; B 29 -15 557 737 ;
+C 99 ; WX 537 ; N c ; B 0 -15 482 477 ;
+C 100 ; WX 667 ; N d ; B 0 -15 660 737 ;
+C 101 ; WX 519 ; N e ; B 0 -15 479 477 ;
+C 102 ; WX 389 ; N f ; B -48 -205 550 737 ; L i fi ; L l fl ;
+C 103 ; WX 611 ; N g ; B -63 -205 604 528 ;
+C 104 ; WX 685 ; N h ; B 0 -15 639 737 ;
+C 105 ; WX 389 ; N i ; B 32 -15 345 737 ;
+C 106 ; WX 370 ; N j ; B -205 -205 347 737 ;
+C 107 ; WX 648 ; N k ; B -11 -15 578 737 ;
+C 108 ; WX 389 ; N l ; B 32 -15 375 737 ;
+C 109 ; WX 944 ; N m ; B 0 -15 909 477 ;
+C 110 ; WX 685 ; N n ; B 0 -15 639 477 ;
+C 111 ; WX 574 ; N o ; B 0 -15 530 477 ;
+C 112 ; WX 648 ; N p ; B -119 -205 590 477 ;
+C 113 ; WX 630 ; N q ; B 0 -205 587 477 ;
+C 114 ; WX 519 ; N r ; B 0 0 527 486 ;
+C 115 ; WX 481 ; N s ; B 0 -15 435 477 ;
+C 116 ; WX 407 ; N t ; B 24 -15 403 650 ;
+C 117 ; WX 685 ; N u ; B 30 -15 635 477 ;
+C 118 ; WX 556 ; N v ; B 30 -15 496 477 ;
+C 119 ; WX 833 ; N w ; B 30 -15 773 477 ;
+C 120 ; WX 574 ; N x ; B -46 -15 574 477 ;
+C 121 ; WX 519 ; N y ; B -66 -205 493 477 ;
+C 122 ; WX 519 ; N z ; B -19 -15 473 477 ;
+C 123 ; WX 407 ; N braceleft ; B 52 -109 408 737 ;
+C 124 ; WX 606 ; N bar ; B 249 -250 357 750 ;
+C 125 ; WX 407 ; N braceright ; B -25 -109 331 737 ;
+C 126 ; WX 606 ; N asciitilde ; B 72 160 534 346 ;
+C 161 ; WX 333 ; N exclamdown ; B -44 -205 289 547 ;
+C 162 ; WX 574 ; N cent ; B 30 -144 512 578 ;
+C 163 ; WX 574 ; N sterling ; B -18 -15 566 705 ;
+C 164 ; WX 167 ; N fraction ; B -166 -15 333 705 ;
+C 165 ; WX 574 ; N yen ; B 17 0 629 690 ;
+C 166 ; WX 574 ; N florin ; B -43 -205 575 737 ;
+C 167 ; WX 500 ; N section ; B -30 -146 515 737 ;
+C 168 ; WX 574 ; N currency ; B 27 84 547 605 ;
+C 169 ; WX 287 ; N quotesingle ; B 112 388 250 737 ;
+C 170 ; WX 481 ; N quotedblleft ; B 54 388 521 737 ;
+C 171 ; WX 481 ; N guillemotleft ; B -35 69 449 407 ;
+C 172 ; WX 278 ; N guilsinglleft ; B -25 69 244 407 ;
+C 173 ; WX 278 ; N guilsinglright ; B -26 69 243 407 ;
+C 174 ; WX 685 ; N fi ; B -70 -205 641 737 ;
+C 175 ; WX 685 ; N fl ; B -70 -205 671 737 ;
+C 177 ; WX 500 ; N endash ; B -47 189 479 287 ;
+C 178 ; WX 500 ; N dagger ; B 48 -146 508 737 ;
+C 179 ; WX 500 ; N daggerdbl ; B -60 -150 508 737 ;
+C 180 ; WX 287 ; N periodcentered ; B 57 200 229 372 ;
+C 182 ; WX 650 ; N paragraph ; B 25 -131 681 722 ;
+C 183 ; WX 606 ; N bullet ; B 122 180 484 542 ;
+C 184 ; WX 259 ; N quotesinglbase ; B -57 -192 170 157 ;
+C 185 ; WX 481 ; N quotedblbase ; B -57 -192 412 157 ;
+C 186 ; WX 481 ; N quotedblright ; B 43 388 510 737 ;
+C 187 ; WX 481 ; N guillemotright ; B -31 69 453 407 ;
+C 188 ; WX 1000 ; N ellipsis ; B 81 -15 919 157 ;
+C 189 ; WX 1167 ; N perthousand ; B 20 -28 1147 727 ;
+C 191 ; WX 481 ; N questiondown ; B 0 -205 372 547 ;
+C 193 ; WX 333 ; N grave ; B 74 538 294 722 ;
+C 194 ; WX 333 ; N acute ; B 123 538 372 722 ;
+C 195 ; WX 333 ; N circumflex ; B 23 533 365 705 ;
+C 196 ; WX 333 ; N tilde ; B 28 561 398 690 ;
+C 197 ; WX 333 ; N macron ; B 47 573 404 649 ;
+C 198 ; WX 333 ; N breve ; B 67 535 390 698 ;
+C 199 ; WX 333 ; N dotaccent ; B 145 546 289 690 ;
+C 200 ; WX 333 ; N dieresis ; B 33 546 393 690 ;
+C 202 ; WX 333 ; N ring ; B 111 522 335 746 ;
+C 203 ; WX 333 ; N cedilla ; B -21 -220 225 3 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 15 538 480 722 ;
+C 206 ; WX 333 ; N ogonek ; B 68 -155 246 -10 ;
+C 207 ; WX 333 ; N caron ; B 60 531 403 705 ;
+C 208 ; WX 1000 ; N emdash ; B -47 189 979 287 ;
+C 225 ; WX 889 ; N AE ; B -86 0 915 722 ;
+C 227 ; WX 412 ; N ordfeminine ; B 47 407 460 705 ;
+C 232 ; WX 704 ; N Lslash ; B -41 0 670 722 ;
+C 233 ; WX 833 ; N Oslash ; B 35 -68 798 790 ;
+C 234 ; WX 963 ; N OE ; B 29 0 989 722 ;
+C 235 ; WX 356 ; N ordmasculine ; B 42 407 394 705 ;
+C 241 ; WX 815 ; N ae ; B -18 -15 775 477 ;
+C 245 ; WX 389 ; N dotlessi ; B 32 -15 345 477 ;
+C 248 ; WX 389 ; N lslash ; B 5 -15 390 737 ;
+C 249 ; WX 574 ; N oslash ; B 0 -121 530 583 ;
+C 250 ; WX 852 ; N oe ; B -6 -15 812 477 ;
+C 251 ; WX 574 ; N germandbls ; B -91 -205 540 737 ;
+C -1 ; WX 519 ; N ecircumflex ; B 0 -15 479 705 ;
+C -1 ; WX 519 ; N edieresis ; B 0 -15 486 690 ;
+C -1 ; WX 667 ; N aacute ; B 6 -15 636 722 ;
+C -1 ; WX 747 ; N registered ; B -2 -15 750 737 ;
+C -1 ; WX 389 ; N icircumflex ; B 21 -15 363 698 ;
+C -1 ; WX 685 ; N udieresis ; B 30 -15 635 690 ;
+C -1 ; WX 574 ; N ograve ; B 0 -15 530 722 ;
+C -1 ; WX 685 ; N uacute ; B 30 -15 635 722 ;
+C -1 ; WX 685 ; N ucircumflex ; B 30 -15 635 705 ;
+C -1 ; WX 741 ; N Aacute ; B -75 0 716 947 ;
+C -1 ; WX 389 ; N igrave ; B 32 -15 345 715 ;
+C -1 ; WX 444 ; N Icircumflex ; B -41 0 485 930 ;
+C -1 ; WX 537 ; N ccedilla ; B 0 -220 482 477 ;
+C -1 ; WX 667 ; N adieresis ; B 6 -15 636 690 ;
+C -1 ; WX 741 ; N Ecircumflex ; B -41 0 730 930 ;
+C -1 ; WX 481 ; N scaron ; B 0 -15 477 705 ;
+C -1 ; WX 648 ; N thorn ; B -119 -205 590 737 ;
+C -1 ; WX 950 ; N trademark ; B 42 317 1017 722 ;
+C -1 ; WX 519 ; N egrave ; B 0 -15 479 722 ;
+C -1 ; WX 344 ; N threesuperior ; B 3 273 361 705 ;
+C -1 ; WX 519 ; N zcaron ; B -19 -15 473 695 ;
+C -1 ; WX 667 ; N atilde ; B 6 -15 636 690 ;
+C -1 ; WX 667 ; N aring ; B 6 -15 636 746 ;
+C -1 ; WX 574 ; N ocircumflex ; B 0 -15 530 705 ;
+C -1 ; WX 741 ; N Edieresis ; B -41 0 730 915 ;
+C -1 ; WX 861 ; N threequarters ; B 35 -15 789 705 ;
+C -1 ; WX 519 ; N ydieresis ; B -66 -205 493 690 ;
+C -1 ; WX 519 ; N yacute ; B -66 -205 493 722 ;
+C -1 ; WX 389 ; N iacute ; B 32 -15 370 715 ;
+C -1 ; WX 741 ; N Acircumflex ; B -75 0 716 930 ;
+C -1 ; WX 833 ; N Uacute ; B 88 -15 900 947 ;
+C -1 ; WX 519 ; N eacute ; B 0 -15 479 722 ;
+C -1 ; WX 833 ; N Ograve ; B 37 -15 796 947 ;
+C -1 ; WX 667 ; N agrave ; B 6 -15 636 722 ;
+C -1 ; WX 833 ; N Udieresis ; B 88 -15 900 915 ;
+C -1 ; WX 667 ; N acircumflex ; B 6 -15 636 705 ;
+C -1 ; WX 444 ; N Igrave ; B -41 0 485 947 ;
+C -1 ; WX 344 ; N twosuperior ; B -17 280 362 705 ;
+C -1 ; WX 833 ; N Ugrave ; B 88 -15 900 947 ;
+C -1 ; WX 861 ; N onequarter ; B 17 -15 789 705 ;
+C -1 ; WX 833 ; N Ucircumflex ; B 88 -15 900 930 ;
+C -1 ; WX 685 ; N Scaron ; B 1 -15 666 930 ;
+C -1 ; WX 444 ; N Idieresis ; B -41 0 509 915 ;
+C -1 ; WX 389 ; N idieresis ; B 31 -15 391 683 ;
+C -1 ; WX 741 ; N Egrave ; B -41 0 730 947 ;
+C -1 ; WX 833 ; N Oacute ; B 37 -15 796 947 ;
+C -1 ; WX 606 ; N divide ; B 50 -40 556 546 ;
+C -1 ; WX 741 ; N Atilde ; B -75 0 716 915 ;
+C -1 ; WX 741 ; N Aring ; B -75 0 716 991 ;
+C -1 ; WX 833 ; N Odieresis ; B 37 -15 796 915 ;
+C -1 ; WX 741 ; N Adieresis ; B -75 0 716 915 ;
+C -1 ; WX 852 ; N Ntilde ; B -61 -10 913 915 ;
+C -1 ; WX 704 ; N Zcaron ; B -33 0 711 930 ;
+C -1 ; WX 741 ; N Thorn ; B -41 0 690 722 ;
+C -1 ; WX 444 ; N Iacute ; B -41 0 488 947 ;
+C -1 ; WX 606 ; N plusminus ; B 50 0 556 506 ;
+C -1 ; WX 606 ; N multiply ; B 65 15 541 491 ;
+C -1 ; WX 741 ; N Eacute ; B -41 0 730 947 ;
+C -1 ; WX 704 ; N Ydieresis ; B 13 0 775 915 ;
+C -1 ; WX 344 ; N onesuperior ; B 19 282 326 705 ;
+C -1 ; WX 685 ; N ugrave ; B 30 -15 635 722 ;
+C -1 ; WX 606 ; N logicalnot ; B 50 103 556 403 ;
+C -1 ; WX 685 ; N ntilde ; B 0 -15 639 690 ;
+C -1 ; WX 833 ; N Otilde ; B 37 -15 796 915 ;
+C -1 ; WX 574 ; N otilde ; B 0 -15 530 690 ;
+C -1 ; WX 759 ; N Ccedilla ; B 37 -220 759 737 ;
+C -1 ; WX 741 ; N Agrave ; B -75 0 716 947 ;
+C -1 ; WX 861 ; N onehalf ; B 17 -15 798 705 ;
+C -1 ; WX 833 ; N Eth ; B -47 0 796 722 ;
+C -1 ; WX 400 ; N degree ; B 86 419 372 705 ;
+C -1 ; WX 704 ; N Yacute ; B 13 0 775 947 ;
+C -1 ; WX 833 ; N Ocircumflex ; B 37 -15 796 930 ;
+C -1 ; WX 574 ; N oacute ; B 0 -15 530 722 ;
+C -1 ; WX 685 ; N mu ; B -89 -205 635 477 ;
+C -1 ; WX 606 ; N minus ; B 50 199 556 307 ;
+C -1 ; WX 574 ; N eth ; B 0 -15 530 752 ;
+C -1 ; WX 574 ; N odieresis ; B 0 -15 530 690 ;
+C -1 ; WX 747 ; N copyright ; B -2 -15 750 737 ;
+C -1 ; WX 606 ; N brokenbar ; B 249 -175 357 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 239
+
+KPX A y -33
+KPX A w -25
+KPX A v -10
+KPX A u -15
+KPX A quoteright -95
+KPX A quotedblright -95
+KPX A Y -70
+KPX A W -84
+KPX A V -100
+KPX A U -32
+KPX A T 5
+KPX A Q 5
+KPX A O 5
+KPX A G 5
+KPX A C 5
+
+KPX B period 15
+KPX B comma 15
+KPX B U 15
+KPX B A -11
+
+KPX C A -5
+
+KPX D period -11
+KPX D comma -11
+KPX D Y 6
+KPX D W -11
+KPX D V -18
+
+KPX F r -27
+KPX F period -91
+KPX F o -47
+KPX F i -41
+KPX F e -41
+KPX F comma -91
+KPX F a -47
+KPX F A -79
+
+KPX J u -39
+KPX J period -74
+KPX J o -40
+KPX J e -33
+KPX J comma -74
+KPX J a -40
+KPX J A -30
+
+KPX K y -48
+KPX K u -4
+KPX K o -4
+KPX K e 18
+
+KPX L y -30
+KPX L quoteright -100
+KPX L quotedblright -100
+KPX L Y -55
+KPX L W -69
+KPX L V -97
+KPX L T -75
+
+KPX N period -49
+KPX N comma -49
+
+KPX O period -18
+KPX O comma -18
+KPX O X -18
+KPX O W -15
+KPX O V -24
+KPX O A -5
+
+KPX P period -100
+KPX P o -40
+KPX P e -33
+KPX P comma -100
+KPX P a -40
+KPX P A -80
+
+KPX R W -14
+KPX R V -24
+
+KPX S period -18
+KPX S comma -18
+
+KPX T y -30
+KPX T w -30
+KPX T u -22
+KPX T r -9
+KPX T period -55
+KPX T o -40
+KPX T i -22
+KPX T hyphen -75
+KPX T h -9
+KPX T e -33
+KPX T comma -55
+KPX T a -40
+KPX T O 11
+KPX T A -60
+
+KPX U period -25
+KPX U comma -25
+KPX U A -42
+
+KPX V u -70
+KPX V semicolon 6
+KPX V period -94
+KPX V o -71
+KPX V i -35
+KPX V hyphen -94
+KPX V e -66
+KPX V comma -94
+KPX V colon -49
+KPX V a -55
+KPX V O -19
+KPX V G -12
+KPX V A -100
+
+KPX W y -41
+KPX W u -25
+KPX W semicolon -22
+KPX W period -86
+KPX W o -33
+KPX W i -27
+KPX W hyphen -61
+KPX W h 5
+KPX W e -39
+KPX W comma -86
+KPX W colon -22
+KPX W a -33
+KPX W O -11
+KPX W A -66
+
+KPX Y u -58
+KPX Y semicolon -55
+KPX Y period -91
+KPX Y o -77
+KPX Y i -22
+KPX Y hyphen -91
+KPX Y e -71
+KPX Y comma -91
+KPX Y colon -55
+KPX Y a -77
+KPX Y A -79
+
+KPX a y -8
+KPX a w -8
+KPX a v 6
+
+KPX b y -6
+KPX b v 8
+KPX b period 6
+KPX b comma 6
+
+KPX c y -20
+KPX c period -8
+KPX c l -13
+KPX c k -8
+KPX c h -18
+KPX c comma -8
+
+KPX colon space -18
+
+KPX comma space -18
+KPX comma quoteright -18
+KPX comma quotedblright -18
+
+KPX d y -15
+KPX d w -15
+
+KPX e y -15
+KPX e x -5
+KPX e w -15
+KPX e p -11
+KPX e g -4
+KPX e b -8
+
+KPX f quoteright 105
+KPX f quotedblright 105
+KPX f period -28
+KPX f o 7
+KPX f l 7
+KPX f i 7
+KPX f e 14
+KPX f dotlessi 7
+KPX f comma -28
+KPX f a 8
+
+KPX g y -11
+KPX g r 11
+KPX g period -5
+KPX g comma -5
+
+KPX h y -20
+
+KPX i v 7
+
+KPX k y -15
+KPX k o -22
+KPX k e -16
+
+KPX l y -7
+KPX l w -7
+
+KPX m y -20
+KPX m u -11
+
+KPX n y -20
+KPX n v -7
+KPX n u -11
+
+KPX o y -11
+KPX o w -8
+KPX o v 6
+
+KPX p y -4
+KPX p period 8
+KPX p comma 8
+
+KPX period space -18
+KPX period quoteright -18
+KPX period quotedblright -18
+
+KPX quotedblleft quoteleft 20
+KPX quotedblleft A -60
+
+KPX quotedblright space -18
+
+KPX quoteleft A -80
+
+KPX quoteright v -16
+KPX quoteright t -22
+KPX quoteright s -46
+KPX quoteright r -9
+KPX quoteright l -22
+KPX quoteright d -41
+
+KPX r y -20
+KPX r v -7
+KPX r u -11
+KPX r t -11
+KPX r semicolon 9
+KPX r s -20
+KPX r quoteright 9
+KPX r period -90
+KPX r p -17
+KPX r o -11
+KPX r l -14
+KPX r k 9
+KPX r i -14
+KPX r hyphen -16
+KPX r g -11
+KPX r e -7
+KPX r d -7
+KPX r comma -90
+KPX r colon 9
+KPX r a -11
+
+KPX s period 11
+KPX s comma 11
+
+KPX semicolon space -18
+
+KPX space quotedblleft -18
+KPX space Y -18
+KPX space W -33
+KPX space V -24
+KPX space T -18
+KPX space A -22
+
+KPX v period -11
+KPX v o -6
+KPX v comma -11
+KPX v a -6
+
+KPX w period -17
+KPX w o -14
+KPX w e -8
+KPX w comma -17
+KPX w a -14
+
+KPX x e 5
+
+KPX y period -25
+KPX y o 8
+KPX y e 15
+KPX y comma -25
+KPX y a 8
+
+KPX z e 4
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 259 225 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 259 225 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 259 225 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 259 225 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 229 245 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 259 225 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 296 225 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 296 225 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 296 225 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 296 225 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 116 225 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 116 225 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 116 225 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 116 225 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 326 225 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 315 225 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 315 225 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 315 225 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 315 225 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 315 225 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 206 225 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 340 225 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 340 225 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 340 225 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 340 225 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 246 225 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 236 225 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 226 225 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 167 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 167 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 167 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 167 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 167 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 167 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 93 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 93 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 93 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 93 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -2 -7 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -2 -7 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -2 -7 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -2 -7 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 176 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 121 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 121 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 121 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 121 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 121 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 74 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 176 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 176 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 176 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 176 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 93 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 93 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 63 -10 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/NewCenturySchlbk-Italic.afm b/tlt3.0/library/afm/NewCenturySchlbk-Italic.afm
new file mode 100644
index 0000000..09d2bff
--- /dev/null
+++ b/tlt3.0/library/afm/NewCenturySchlbk-Italic.afm
@@ -0,0 +1,537 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue May 28 16:40:04 1991
+Comment UniqueID 35028
+Comment VMusage 31423 38315
+FontName NewCenturySchlbk-Italic
+FullName New Century Schoolbook Italic
+FamilyName New Century Schoolbook
+Weight Medium
+ItalicAngle -16
+IsFixedPitch false
+FontBBox -166 -250 994 958
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.006
+Notice Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 722
+XHeight 466
+Ascender 737
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 17 -15 303 737 ;
+C 34 ; WX 400 ; N quotedbl ; B 127 463 363 737 ;
+C 35 ; WX 556 ; N numbersign ; B 28 0 528 690 ;
+C 36 ; WX 556 ; N dollar ; B 4 -142 536 808 ;
+C 37 ; WX 833 ; N percent ; B 43 -15 790 705 ;
+C 38 ; WX 852 ; N ampersand ; B 24 -15 773 737 ;
+C 39 ; WX 204 ; N quoteright ; B 39 463 229 737 ;
+C 40 ; WX 333 ; N parenleft ; B 53 -117 411 745 ;
+C 41 ; WX 333 ; N parenright ; B -93 -117 265 745 ;
+C 42 ; WX 500 ; N asterisk ; B 80 318 500 737 ;
+C 43 ; WX 606 ; N plus ; B 50 0 556 506 ;
+C 44 ; WX 278 ; N comma ; B -39 -165 151 109 ;
+C 45 ; WX 333 ; N hyphen ; B 32 202 259 274 ;
+C 46 ; WX 278 ; N period ; B 17 -15 141 109 ;
+C 47 ; WX 606 ; N slash ; B 132 -15 474 737 ;
+C 48 ; WX 556 ; N zero ; B 30 -15 526 705 ;
+C 49 ; WX 556 ; N one ; B 50 0 459 705 ;
+C 50 ; WX 556 ; N two ; B -37 0 506 705 ;
+C 51 ; WX 556 ; N three ; B -2 -15 506 705 ;
+C 52 ; WX 556 ; N four ; B -8 0 512 705 ;
+C 53 ; WX 556 ; N five ; B 4 -15 540 705 ;
+C 54 ; WX 556 ; N six ; B 36 -15 548 705 ;
+C 55 ; WX 556 ; N seven ; B 69 -15 561 705 ;
+C 56 ; WX 556 ; N eight ; B 6 -15 526 705 ;
+C 57 ; WX 556 ; N nine ; B 8 -15 520 705 ;
+C 58 ; WX 278 ; N colon ; B 17 -15 229 466 ;
+C 59 ; WX 278 ; N semicolon ; B -39 -165 229 466 ;
+C 60 ; WX 606 ; N less ; B 36 -8 542 514 ;
+C 61 ; WX 606 ; N equal ; B 50 117 556 389 ;
+C 62 ; WX 606 ; N greater ; B 64 -8 570 514 ;
+C 63 ; WX 444 ; N question ; B 102 -15 417 737 ;
+C 64 ; WX 747 ; N at ; B -2 -15 750 737 ;
+C 65 ; WX 704 ; N A ; B -87 0 668 737 ;
+C 66 ; WX 722 ; N B ; B -33 0 670 722 ;
+C 67 ; WX 722 ; N C ; B 40 -15 712 737 ;
+C 68 ; WX 778 ; N D ; B -33 0 738 722 ;
+C 69 ; WX 722 ; N E ; B -33 0 700 722 ;
+C 70 ; WX 667 ; N F ; B -33 0 700 722 ;
+C 71 ; WX 778 ; N G ; B 40 -15 763 737 ;
+C 72 ; WX 833 ; N H ; B -33 0 866 722 ;
+C 73 ; WX 407 ; N I ; B -33 0 435 722 ;
+C 74 ; WX 611 ; N J ; B -14 -15 651 722 ;
+C 75 ; WX 741 ; N K ; B -33 0 816 722 ;
+C 76 ; WX 667 ; N L ; B -33 0 627 722 ;
+C 77 ; WX 944 ; N M ; B -33 0 977 722 ;
+C 78 ; WX 815 ; N N ; B -51 -15 866 722 ;
+C 79 ; WX 778 ; N O ; B 40 -15 738 737 ;
+C 80 ; WX 667 ; N P ; B -33 0 667 722 ;
+C 81 ; WX 778 ; N Q ; B 40 -190 738 737 ;
+C 82 ; WX 741 ; N R ; B -45 -15 692 722 ;
+C 83 ; WX 667 ; N S ; B -6 -15 638 737 ;
+C 84 ; WX 685 ; N T ; B 40 0 725 722 ;
+C 85 ; WX 815 ; N U ; B 93 -15 867 722 ;
+C 86 ; WX 704 ; N V ; B 36 -10 779 722 ;
+C 87 ; WX 926 ; N W ; B 53 -10 978 722 ;
+C 88 ; WX 704 ; N X ; B -75 0 779 722 ;
+C 89 ; WX 685 ; N Y ; B 31 0 760 722 ;
+C 90 ; WX 667 ; N Z ; B -25 0 667 722 ;
+C 91 ; WX 333 ; N bracketleft ; B -55 -109 388 737 ;
+C 92 ; WX 606 ; N backslash ; B 132 -15 474 737 ;
+C 93 ; WX 333 ; N bracketright ; B -77 -109 366 737 ;
+C 94 ; WX 606 ; N asciicircum ; B 89 325 517 690 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 204 ; N quoteleft ; B 39 463 229 737 ;
+C 97 ; WX 574 ; N a ; B 2 -15 524 466 ;
+C 98 ; WX 556 ; N b ; B 32 -15 488 737 ;
+C 99 ; WX 444 ; N c ; B 2 -15 394 466 ;
+C 100 ; WX 611 ; N d ; B 2 -15 585 737 ;
+C 101 ; WX 444 ; N e ; B -6 -15 388 466 ;
+C 102 ; WX 333 ; N f ; B -68 -205 470 737 ; L i fi ; L l fl ;
+C 103 ; WX 537 ; N g ; B -79 -205 523 497 ;
+C 104 ; WX 611 ; N h ; B 14 -15 562 737 ;
+C 105 ; WX 333 ; N i ; B 29 -15 282 715 ;
+C 106 ; WX 315 ; N j ; B -166 -205 318 715 ;
+C 107 ; WX 556 ; N k ; B 0 -15 497 737 ;
+C 108 ; WX 333 ; N l ; B 14 -15 292 737 ;
+C 109 ; WX 889 ; N m ; B 14 -15 840 466 ;
+C 110 ; WX 611 ; N n ; B 14 -15 562 466 ;
+C 111 ; WX 500 ; N o ; B 2 -15 450 466 ;
+C 112 ; WX 574 ; N p ; B -101 -205 506 466 ;
+C 113 ; WX 556 ; N q ; B 2 -205 500 466 ;
+C 114 ; WX 444 ; N r ; B 10 0 434 466 ;
+C 115 ; WX 444 ; N s ; B 2 -15 394 466 ;
+C 116 ; WX 352 ; N t ; B 24 -15 328 619 ;
+C 117 ; WX 611 ; N u ; B 44 -15 556 466 ;
+C 118 ; WX 519 ; N v ; B 31 -15 447 466 ;
+C 119 ; WX 778 ; N w ; B 31 -15 706 466 ;
+C 120 ; WX 500 ; N x ; B -33 -15 471 466 ;
+C 121 ; WX 500 ; N y ; B -83 -205 450 466 ;
+C 122 ; WX 463 ; N z ; B -33 -15 416 466 ;
+C 123 ; WX 333 ; N braceleft ; B 38 -109 394 737 ;
+C 124 ; WX 606 ; N bar ; B 267 -250 339 750 ;
+C 125 ; WX 333 ; N braceright ; B -87 -109 269 737 ;
+C 126 ; WX 606 ; N asciitilde ; B 72 184 534 322 ;
+C 161 ; WX 333 ; N exclamdown ; B -22 -205 264 547 ;
+C 162 ; WX 556 ; N cent ; B 62 -144 486 580 ;
+C 163 ; WX 556 ; N sterling ; B -13 -15 544 705 ;
+C 164 ; WX 167 ; N fraction ; B -134 -15 301 705 ;
+C 165 ; WX 556 ; N yen ; B 40 0 624 690 ;
+C 166 ; WX 556 ; N florin ; B -58 -205 569 737 ;
+C 167 ; WX 500 ; N section ; B -10 -147 480 737 ;
+C 168 ; WX 556 ; N currency ; B 26 93 530 597 ;
+C 169 ; WX 278 ; N quotesingle ; B 151 463 237 737 ;
+C 170 ; WX 389 ; N quotedblleft ; B 39 463 406 737 ;
+C 171 ; WX 426 ; N guillemotleft ; B -15 74 402 402 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 40 74 259 402 ;
+C 173 ; WX 333 ; N guilsinglright ; B 40 74 259 402 ;
+C 174 ; WX 611 ; N fi ; B -68 -205 555 737 ;
+C 175 ; WX 611 ; N fl ; B -68 -205 587 737 ;
+C 177 ; WX 500 ; N endash ; B -27 208 487 268 ;
+C 178 ; WX 500 ; N dagger ; B 51 -147 506 737 ;
+C 179 ; WX 500 ; N daggerdbl ; B -54 -147 506 737 ;
+C 180 ; WX 278 ; N periodcentered ; B 71 238 207 374 ;
+C 182 ; WX 650 ; N paragraph ; B 48 -132 665 722 ;
+C 183 ; WX 606 ; N bullet ; B 122 180 484 542 ;
+C 184 ; WX 204 ; N quotesinglbase ; B -78 -165 112 109 ;
+C 185 ; WX 389 ; N quotedblbase ; B -78 -165 289 109 ;
+C 186 ; WX 389 ; N quotedblright ; B 39 463 406 737 ;
+C 187 ; WX 426 ; N guillemotright ; B -15 74 402 402 ;
+C 188 ; WX 1000 ; N ellipsis ; B 59 -15 849 109 ;
+C 189 ; WX 1000 ; N perthousand ; B 6 -15 994 705 ;
+C 191 ; WX 444 ; N questiondown ; B -3 -205 312 547 ;
+C 193 ; WX 333 ; N grave ; B 71 518 262 690 ;
+C 194 ; WX 333 ; N acute ; B 132 518 355 690 ;
+C 195 ; WX 333 ; N circumflex ; B 37 518 331 690 ;
+C 196 ; WX 333 ; N tilde ; B 52 547 383 649 ;
+C 197 ; WX 333 ; N macron ; B 52 560 363 610 ;
+C 198 ; WX 333 ; N breve ; B 69 518 370 677 ;
+C 199 ; WX 333 ; N dotaccent ; B 146 544 248 646 ;
+C 200 ; WX 333 ; N dieresis ; B 59 544 359 646 ;
+C 202 ; WX 333 ; N ring ; B 114 512 314 712 ;
+C 203 ; WX 333 ; N cedilla ; B 3 -215 215 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 32 518 455 690 ;
+C 206 ; WX 333 ; N ogonek ; B 68 -215 254 0 ;
+C 207 ; WX 333 ; N caron ; B 73 518 378 690 ;
+C 208 ; WX 1000 ; N emdash ; B -27 208 987 268 ;
+C 225 ; WX 870 ; N AE ; B -87 0 888 722 ;
+C 227 ; WX 422 ; N ordfeminine ; B 72 416 420 705 ;
+C 232 ; WX 667 ; N Lslash ; B -33 0 627 722 ;
+C 233 ; WX 778 ; N Oslash ; B 16 -68 748 780 ;
+C 234 ; WX 981 ; N OE ; B 40 0 975 722 ;
+C 235 ; WX 372 ; N ordmasculine ; B 66 416 370 705 ;
+C 241 ; WX 722 ; N ae ; B -18 -15 666 466 ;
+C 245 ; WX 333 ; N dotlessi ; B 29 -15 282 466 ;
+C 248 ; WX 333 ; N lslash ; B -25 -15 340 737 ;
+C 249 ; WX 500 ; N oslash ; B 2 -121 450 549 ;
+C 250 ; WX 778 ; N oe ; B 2 -15 722 466 ;
+C 251 ; WX 556 ; N germandbls ; B -76 -205 525 737 ;
+C -1 ; WX 444 ; N ecircumflex ; B -6 -15 388 690 ;
+C -1 ; WX 444 ; N edieresis ; B -6 -15 415 646 ;
+C -1 ; WX 574 ; N aacute ; B 2 -15 524 690 ;
+C -1 ; WX 747 ; N registered ; B -2 -15 750 737 ;
+C -1 ; WX 333 ; N icircumflex ; B 29 -15 331 690 ;
+C -1 ; WX 611 ; N udieresis ; B 44 -15 556 646 ;
+C -1 ; WX 500 ; N ograve ; B 2 -15 450 690 ;
+C -1 ; WX 611 ; N uacute ; B 44 -15 556 690 ;
+C -1 ; WX 611 ; N ucircumflex ; B 44 -15 556 690 ;
+C -1 ; WX 704 ; N Aacute ; B -87 0 668 946 ;
+C -1 ; WX 333 ; N igrave ; B 29 -15 282 690 ;
+C -1 ; WX 407 ; N Icircumflex ; B -33 0 435 946 ;
+C -1 ; WX 444 ; N ccedilla ; B 2 -215 394 466 ;
+C -1 ; WX 574 ; N adieresis ; B 2 -15 524 646 ;
+C -1 ; WX 722 ; N Ecircumflex ; B -33 0 700 946 ;
+C -1 ; WX 444 ; N scaron ; B 2 -15 434 690 ;
+C -1 ; WX 574 ; N thorn ; B -101 -205 506 737 ;
+C -1 ; WX 950 ; N trademark ; B 32 318 968 722 ;
+C -1 ; WX 444 ; N egrave ; B -6 -15 388 690 ;
+C -1 ; WX 333 ; N threesuperior ; B 22 273 359 705 ;
+C -1 ; WX 463 ; N zcaron ; B -33 -15 443 690 ;
+C -1 ; WX 574 ; N atilde ; B 2 -15 524 649 ;
+C -1 ; WX 574 ; N aring ; B 2 -15 524 712 ;
+C -1 ; WX 500 ; N ocircumflex ; B 2 -15 450 690 ;
+C -1 ; WX 722 ; N Edieresis ; B -33 0 700 902 ;
+C -1 ; WX 834 ; N threequarters ; B 22 -15 782 705 ;
+C -1 ; WX 500 ; N ydieresis ; B -83 -205 450 646 ;
+C -1 ; WX 500 ; N yacute ; B -83 -205 450 690 ;
+C -1 ; WX 333 ; N iacute ; B 29 -15 355 690 ;
+C -1 ; WX 704 ; N Acircumflex ; B -87 0 668 946 ;
+C -1 ; WX 815 ; N Uacute ; B 93 -15 867 946 ;
+C -1 ; WX 444 ; N eacute ; B -6 -15 411 690 ;
+C -1 ; WX 778 ; N Ograve ; B 40 -15 738 946 ;
+C -1 ; WX 574 ; N agrave ; B 2 -15 524 690 ;
+C -1 ; WX 815 ; N Udieresis ; B 93 -15 867 902 ;
+C -1 ; WX 574 ; N acircumflex ; B 2 -15 524 690 ;
+C -1 ; WX 407 ; N Igrave ; B -33 0 435 946 ;
+C -1 ; WX 333 ; N twosuperior ; B 0 282 359 705 ;
+C -1 ; WX 815 ; N Ugrave ; B 93 -15 867 946 ;
+C -1 ; WX 834 ; N onequarter ; B 34 -15 782 705 ;
+C -1 ; WX 815 ; N Ucircumflex ; B 93 -15 867 946 ;
+C -1 ; WX 667 ; N Scaron ; B -6 -15 638 946 ;
+C -1 ; WX 407 ; N Idieresis ; B -33 0 456 902 ;
+C -1 ; WX 333 ; N idieresis ; B 29 -15 359 646 ;
+C -1 ; WX 722 ; N Egrave ; B -33 0 700 946 ;
+C -1 ; WX 778 ; N Oacute ; B 40 -15 738 946 ;
+C -1 ; WX 606 ; N divide ; B 50 -22 556 528 ;
+C -1 ; WX 704 ; N Atilde ; B -87 0 668 905 ;
+C -1 ; WX 704 ; N Aring ; B -87 0 668 958 ;
+C -1 ; WX 778 ; N Odieresis ; B 40 -15 738 902 ;
+C -1 ; WX 704 ; N Adieresis ; B -87 0 668 902 ;
+C -1 ; WX 815 ; N Ntilde ; B -51 -15 866 905 ;
+C -1 ; WX 667 ; N Zcaron ; B -25 0 667 946 ;
+C -1 ; WX 667 ; N Thorn ; B -33 0 627 722 ;
+C -1 ; WX 407 ; N Iacute ; B -33 0 452 946 ;
+C -1 ; WX 606 ; N plusminus ; B 50 0 556 506 ;
+C -1 ; WX 606 ; N multiply ; B 74 24 532 482 ;
+C -1 ; WX 722 ; N Eacute ; B -33 0 700 946 ;
+C -1 ; WX 685 ; N Ydieresis ; B 31 0 760 902 ;
+C -1 ; WX 333 ; N onesuperior ; B 34 282 311 705 ;
+C -1 ; WX 611 ; N ugrave ; B 44 -15 556 690 ;
+C -1 ; WX 606 ; N logicalnot ; B 50 108 556 389 ;
+C -1 ; WX 611 ; N ntilde ; B 14 -15 562 649 ;
+C -1 ; WX 778 ; N Otilde ; B 40 -15 738 905 ;
+C -1 ; WX 500 ; N otilde ; B 2 -15 467 649 ;
+C -1 ; WX 722 ; N Ccedilla ; B 40 -215 712 737 ;
+C -1 ; WX 704 ; N Agrave ; B -87 0 668 946 ;
+C -1 ; WX 834 ; N onehalf ; B 34 -15 776 705 ;
+C -1 ; WX 778 ; N Eth ; B -33 0 738 722 ;
+C -1 ; WX 400 ; N degree ; B 86 419 372 705 ;
+C -1 ; WX 685 ; N Yacute ; B 31 0 760 946 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 40 -15 738 946 ;
+C -1 ; WX 500 ; N oacute ; B 2 -15 450 690 ;
+C -1 ; WX 611 ; N mu ; B -60 -205 556 466 ;
+C -1 ; WX 606 ; N minus ; B 50 217 556 289 ;
+C -1 ; WX 500 ; N eth ; B 2 -15 450 737 ;
+C -1 ; WX 500 ; N odieresis ; B 2 -15 450 646 ;
+C -1 ; WX 747 ; N copyright ; B -2 -15 750 737 ;
+C -1 ; WX 606 ; N brokenbar ; B 267 -175 339 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 181
+
+KPX A y -55
+KPX A w -18
+KPX A v -18
+KPX A u -18
+KPX A quoteright -125
+KPX A quotedblright -125
+KPX A Y -55
+KPX A W -74
+KPX A V -74
+KPX A U -37
+KPX A T -30
+KPX A Q -18
+KPX A O -18
+KPX A G -18
+KPX A C -18
+
+KPX B period -50
+KPX B comma -50
+
+KPX C period -50
+KPX C comma -50
+
+KPX D period -50
+KPX D comma -50
+KPX D Y -18
+KPX D W -18
+KPX D V -18
+
+KPX F r -55
+KPX F period -125
+KPX F o -55
+KPX F i -10
+KPX F e -55
+KPX F comma -125
+KPX F a -55
+KPX F A -35
+
+KPX G period -50
+KPX G comma -50
+
+KPX J u -18
+KPX J period -100
+KPX J o -37
+KPX J e -37
+KPX J comma -100
+KPX J a -37
+KPX J A -18
+
+KPX L y -50
+KPX L quoteright -125
+KPX L quotedblright -125
+KPX L Y -100
+KPX L W -100
+KPX L V -100
+KPX L T -100
+
+KPX N period -60
+KPX N comma -60
+
+KPX O period -50
+KPX O comma -50
+KPX O Y -18
+KPX O X -18
+KPX O V -18
+KPX O T 18
+
+KPX P period -125
+KPX P o -55
+KPX P e -55
+KPX P comma -125
+KPX P a -55
+KPX P A -50
+
+KPX Q period -20
+KPX Q comma -20
+
+KPX R Y -18
+KPX R W -18
+KPX R V -18
+KPX R U -18
+
+KPX S period -50
+KPX S comma -50
+
+KPX T y -50
+KPX T w -50
+KPX T u -50
+KPX T semicolon -50
+KPX T r -50
+KPX T period -100
+KPX T o -74
+KPX T i -18
+KPX T hyphen -100
+KPX T h -25
+KPX T e -74
+KPX T comma -100
+KPX T colon -50
+KPX T a -74
+KPX T O 18
+
+KPX U period -100
+KPX U comma -100
+KPX U A -18
+
+KPX V u -75
+KPX V semicolon -75
+KPX V period -100
+KPX V o -75
+KPX V i -50
+KPX V hyphen -100
+KPX V e -75
+KPX V comma -100
+KPX V colon -75
+KPX V a -75
+KPX V A -37
+
+KPX W y -55
+KPX W u -55
+KPX W semicolon -75
+KPX W period -100
+KPX W o -55
+KPX W i -20
+KPX W hyphen -75
+KPX W h -20
+KPX W e -55
+KPX W comma -100
+KPX W colon -75
+KPX W a -55
+KPX W A -55
+
+KPX Y u -100
+KPX Y semicolon -75
+KPX Y period -100
+KPX Y o -100
+KPX Y i -25
+KPX Y hyphen -100
+KPX Y e -100
+KPX Y comma -100
+KPX Y colon -75
+KPX Y a -100
+KPX Y A -55
+
+KPX b period -50
+KPX b comma -50
+KPX b b -10
+
+KPX c period -50
+KPX c k -18
+KPX c h -18
+KPX c comma -50
+
+KPX colon space -37
+
+KPX comma space -37
+KPX comma quoteright -37
+KPX comma quotedblright -37
+
+KPX e period -37
+KPX e comma -37
+
+KPX f quoteright 75
+KPX f quotedblright 75
+KPX f period -75
+KPX f o -10
+KPX f comma -75
+
+KPX g period -50
+KPX g comma -50
+
+KPX l y -10
+
+KPX o period -50
+KPX o comma -50
+
+KPX p period -50
+KPX p comma -50
+
+KPX period space -37
+KPX period quoteright -37
+KPX period quotedblright -37
+
+KPX quotedblleft A -75
+
+KPX quotedblright space -37
+
+KPX quoteleft quoteleft -37
+KPX quoteleft A -75
+
+KPX quoteright s -25
+KPX quoteright quoteright -37
+KPX quoteright d -37
+
+KPX r semicolon -25
+KPX r s -10
+KPX r period -125
+KPX r k -18
+KPX r hyphen -75
+KPX r comma -125
+KPX r colon -25
+
+KPX s period -50
+KPX s comma -50
+
+KPX semicolon space -37
+
+KPX space quoteleft -37
+KPX space quotedblleft -37
+KPX space Y -37
+KPX space W -37
+KPX space V -37
+KPX space T -37
+KPX space A -37
+
+KPX v period -75
+KPX v comma -75
+
+KPX w period -75
+KPX w comma -75
+
+KPX y period -75
+KPX y comma -75
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 246 256 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 246 256 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 231 256 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 246 256 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 216 246 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 231 256 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 255 256 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 255 256 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 255 256 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 255 256 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 97 256 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 97 256 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 97 256 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 97 256 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 301 256 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 283 256 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 283 256 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 283 256 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 283 256 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 283 256 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 227 256 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 301 256 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 301 256 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 301 256 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 301 256 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 256 256 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 236 256 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 227 256 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 121 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 121 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 121 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 121 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 121 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 121 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex 0 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis 0 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 56 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 65 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/NewCenturySchlbk-Roman.afm b/tlt3.0/library/afm/NewCenturySchlbk-Roman.afm
new file mode 100644
index 0000000..80e9221
--- /dev/null
+++ b/tlt3.0/library/afm/NewCenturySchlbk-Roman.afm
@@ -0,0 +1,525 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue May 28 16:31:51 1991
+Comment UniqueID 35025
+Comment VMusage 30420 37312
+FontName NewCenturySchlbk-Roman
+FullName New Century Schoolbook Roman
+FamilyName New Century Schoolbook
+Weight Roman
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -195 -250 1000 965
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1991 Adobe Systems Incorporated. All Rights Reserved.
+EncodingScheme AdobeStandardEncoding
+CapHeight 722
+XHeight 464
+Ascender 737
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 296 ; N exclam ; B 86 -15 210 737 ;
+C 34 ; WX 389 ; N quotedbl ; B 61 443 328 737 ;
+C 35 ; WX 556 ; N numbersign ; B 28 0 528 690 ;
+C 36 ; WX 556 ; N dollar ; B 45 -138 511 813 ;
+C 37 ; WX 833 ; N percent ; B 43 -15 790 705 ;
+C 38 ; WX 815 ; N ampersand ; B 51 -15 775 737 ;
+C 39 ; WX 204 ; N quoteright ; B 25 443 179 737 ;
+C 40 ; WX 333 ; N parenleft ; B 40 -117 279 745 ;
+C 41 ; WX 333 ; N parenright ; B 54 -117 293 745 ;
+C 42 ; WX 500 ; N asterisk ; B 57 306 443 737 ;
+C 43 ; WX 606 ; N plus ; B 50 0 556 506 ;
+C 44 ; WX 278 ; N comma ; B 62 -185 216 109 ;
+C 45 ; WX 333 ; N hyphen ; B 42 199 291 277 ;
+C 46 ; WX 278 ; N period ; B 77 -15 201 109 ;
+C 47 ; WX 278 ; N slash ; B -32 -15 310 737 ;
+C 48 ; WX 556 ; N zero ; B 42 -15 514 705 ;
+C 49 ; WX 556 ; N one ; B 100 0 496 705 ;
+C 50 ; WX 556 ; N two ; B 35 0 505 705 ;
+C 51 ; WX 556 ; N three ; B 42 -15 498 705 ;
+C 52 ; WX 556 ; N four ; B 28 0 528 705 ;
+C 53 ; WX 556 ; N five ; B 46 -15 502 705 ;
+C 54 ; WX 556 ; N six ; B 41 -15 515 705 ;
+C 55 ; WX 556 ; N seven ; B 59 -15 508 705 ;
+C 56 ; WX 556 ; N eight ; B 42 -15 514 705 ;
+C 57 ; WX 556 ; N nine ; B 41 -15 515 705 ;
+C 58 ; WX 278 ; N colon ; B 77 -15 201 474 ;
+C 59 ; WX 278 ; N semicolon ; B 62 -185 216 474 ;
+C 60 ; WX 606 ; N less ; B 50 -8 556 514 ;
+C 61 ; WX 606 ; N equal ; B 50 117 556 389 ;
+C 62 ; WX 606 ; N greater ; B 50 -8 556 514 ;
+C 63 ; WX 444 ; N question ; B 29 -15 415 737 ;
+C 64 ; WX 737 ; N at ; B -8 -15 744 737 ;
+C 65 ; WX 722 ; N A ; B -8 0 730 737 ;
+C 66 ; WX 722 ; N B ; B 29 0 669 722 ;
+C 67 ; WX 722 ; N C ; B 45 -15 668 737 ;
+C 68 ; WX 778 ; N D ; B 29 0 733 722 ;
+C 69 ; WX 722 ; N E ; B 29 0 663 722 ;
+C 70 ; WX 667 ; N F ; B 29 0 638 722 ;
+C 71 ; WX 778 ; N G ; B 45 -15 775 737 ;
+C 72 ; WX 833 ; N H ; B 29 0 804 722 ;
+C 73 ; WX 407 ; N I ; B 38 0 369 722 ;
+C 74 ; WX 556 ; N J ; B 5 -15 540 722 ;
+C 75 ; WX 778 ; N K ; B 29 0 803 722 ;
+C 76 ; WX 667 ; N L ; B 29 0 644 722 ;
+C 77 ; WX 944 ; N M ; B 29 0 915 722 ;
+C 78 ; WX 815 ; N N ; B 24 -15 791 722 ;
+C 79 ; WX 778 ; N O ; B 45 -15 733 737 ;
+C 80 ; WX 667 ; N P ; B 29 0 650 722 ;
+C 81 ; WX 778 ; N Q ; B 45 -190 748 737 ;
+C 82 ; WX 722 ; N R ; B 29 -15 713 722 ;
+C 83 ; WX 630 ; N S ; B 47 -15 583 737 ;
+C 84 ; WX 667 ; N T ; B 19 0 648 722 ;
+C 85 ; WX 815 ; N U ; B 16 -15 799 722 ;
+C 86 ; WX 722 ; N V ; B -8 -10 730 722 ;
+C 87 ; WX 981 ; N W ; B 5 -10 976 722 ;
+C 88 ; WX 704 ; N X ; B -8 0 712 722 ;
+C 89 ; WX 704 ; N Y ; B -11 0 715 722 ;
+C 90 ; WX 611 ; N Z ; B 24 0 576 722 ;
+C 91 ; WX 333 ; N bracketleft ; B 126 -109 315 737 ;
+C 92 ; WX 606 ; N backslash ; B 132 -15 474 737 ;
+C 93 ; WX 333 ; N bracketright ; B 18 -109 207 737 ;
+C 94 ; WX 606 ; N asciicircum ; B 89 325 517 690 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 204 ; N quoteleft ; B 25 443 179 737 ;
+C 97 ; WX 556 ; N a ; B 44 -15 542 479 ;
+C 98 ; WX 556 ; N b ; B 10 -15 522 737 ;
+C 99 ; WX 444 ; N c ; B 34 -15 426 479 ;
+C 100 ; WX 574 ; N d ; B 34 -15 552 737 ;
+C 101 ; WX 500 ; N e ; B 34 -15 466 479 ;
+C 102 ; WX 333 ; N f ; B 18 0 437 737 ; L i fi ; L l fl ;
+C 103 ; WX 537 ; N g ; B 23 -205 542 494 ;
+C 104 ; WX 611 ; N h ; B 7 0 592 737 ;
+C 105 ; WX 315 ; N i ; B 18 0 286 722 ;
+C 106 ; WX 296 ; N j ; B -86 -205 216 722 ;
+C 107 ; WX 593 ; N k ; B 10 0 589 737 ;
+C 108 ; WX 315 ; N l ; B 18 0 286 737 ;
+C 109 ; WX 889 ; N m ; B 26 0 863 479 ;
+C 110 ; WX 611 ; N n ; B 22 0 589 479 ;
+C 111 ; WX 500 ; N o ; B 34 -15 466 479 ;
+C 112 ; WX 574 ; N p ; B 22 -205 540 479 ;
+C 113 ; WX 556 ; N q ; B 34 -205 552 479 ;
+C 114 ; WX 444 ; N r ; B 18 0 434 479 ;
+C 115 ; WX 463 ; N s ; B 46 -15 417 479 ;
+C 116 ; WX 389 ; N t ; B 18 -15 371 666 ;
+C 117 ; WX 611 ; N u ; B 22 -15 589 464 ;
+C 118 ; WX 537 ; N v ; B -6 -10 515 464 ;
+C 119 ; WX 778 ; N w ; B 1 -10 749 464 ;
+C 120 ; WX 537 ; N x ; B 8 0 529 464 ;
+C 121 ; WX 537 ; N y ; B 4 -205 533 464 ;
+C 122 ; WX 481 ; N z ; B 42 0 439 464 ;
+C 123 ; WX 333 ; N braceleft ; B 54 -109 279 737 ;
+C 124 ; WX 606 ; N bar ; B 267 -250 339 750 ;
+C 125 ; WX 333 ; N braceright ; B 54 -109 279 737 ;
+C 126 ; WX 606 ; N asciitilde ; B 72 184 534 322 ;
+C 161 ; WX 296 ; N exclamdown ; B 86 -205 210 547 ;
+C 162 ; WX 556 ; N cent ; B 74 -141 482 584 ;
+C 163 ; WX 556 ; N sterling ; B 18 -15 538 705 ;
+C 164 ; WX 167 ; N fraction ; B -195 -15 362 705 ;
+C 165 ; WX 556 ; N yen ; B -1 0 557 690 ;
+C 166 ; WX 556 ; N florin ; B 0 -205 538 737 ;
+C 167 ; WX 500 ; N section ; B 55 -147 445 737 ;
+C 168 ; WX 556 ; N currency ; B 26 93 530 597 ;
+C 169 ; WX 204 ; N quotesingle ; B 59 443 145 737 ;
+C 170 ; WX 389 ; N quotedblleft ; B 25 443 364 737 ;
+C 171 ; WX 426 ; N guillemotleft ; B 39 78 387 398 ;
+C 172 ; WX 259 ; N guilsinglleft ; B 39 78 220 398 ;
+C 173 ; WX 259 ; N guilsinglright ; B 39 78 220 398 ;
+C 174 ; WX 611 ; N fi ; B 18 0 582 737 ;
+C 175 ; WX 611 ; N fl ; B 18 0 582 737 ;
+C 177 ; WX 556 ; N endash ; B 0 208 556 268 ;
+C 178 ; WX 500 ; N dagger ; B 42 -147 458 737 ;
+C 179 ; WX 500 ; N daggerdbl ; B 42 -149 458 737 ;
+C 180 ; WX 278 ; N periodcentered ; B 71 238 207 374 ;
+C 182 ; WX 606 ; N paragraph ; B 60 -132 546 722 ;
+C 183 ; WX 606 ; N bullet ; B 122 180 484 542 ;
+C 184 ; WX 204 ; N quotesinglbase ; B 25 -185 179 109 ;
+C 185 ; WX 389 ; N quotedblbase ; B 25 -185 364 109 ;
+C 186 ; WX 389 ; N quotedblright ; B 25 443 364 737 ;
+C 187 ; WX 426 ; N guillemotright ; B 39 78 387 398 ;
+C 188 ; WX 1000 ; N ellipsis ; B 105 -15 895 109 ;
+C 189 ; WX 1000 ; N perthousand ; B 6 -15 994 705 ;
+C 191 ; WX 444 ; N questiondown ; B 29 -205 415 547 ;
+C 193 ; WX 333 ; N grave ; B 17 528 242 699 ;
+C 194 ; WX 333 ; N acute ; B 91 528 316 699 ;
+C 195 ; WX 333 ; N circumflex ; B 10 528 323 695 ;
+C 196 ; WX 333 ; N tilde ; B 1 553 332 655 ;
+C 197 ; WX 333 ; N macron ; B 10 568 323 623 ;
+C 198 ; WX 333 ; N breve ; B 25 528 308 685 ;
+C 199 ; WX 333 ; N dotaccent ; B 116 543 218 645 ;
+C 200 ; WX 333 ; N dieresis ; B 16 543 317 645 ;
+C 202 ; WX 333 ; N ring ; B 66 522 266 722 ;
+C 203 ; WX 333 ; N cedilla ; B 29 -215 237 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -9 528 416 699 ;
+C 206 ; WX 333 ; N ogonek ; B 68 -215 254 0 ;
+C 207 ; WX 333 ; N caron ; B 10 528 323 695 ;
+C 208 ; WX 1000 ; N emdash ; B 0 208 1000 268 ;
+C 225 ; WX 1000 ; N AE ; B 0 0 962 722 ;
+C 227 ; WX 334 ; N ordfeminine ; B -4 407 338 705 ;
+C 232 ; WX 667 ; N Lslash ; B 29 0 644 722 ;
+C 233 ; WX 778 ; N Oslash ; B 45 -56 733 778 ;
+C 234 ; WX 1000 ; N OE ; B 21 0 979 722 ;
+C 235 ; WX 300 ; N ordmasculine ; B 4 407 296 705 ;
+C 241 ; WX 796 ; N ae ; B 34 -15 762 479 ;
+C 245 ; WX 315 ; N dotlessi ; B 18 0 286 464 ;
+C 248 ; WX 315 ; N lslash ; B 18 0 286 737 ;
+C 249 ; WX 500 ; N oslash ; B 34 -97 466 561 ;
+C 250 ; WX 833 ; N oe ; B 34 -15 799 479 ;
+C 251 ; WX 574 ; N germandbls ; B 30 -15 537 737 ;
+C -1 ; WX 500 ; N ecircumflex ; B 34 -15 466 695 ;
+C -1 ; WX 500 ; N edieresis ; B 34 -15 466 645 ;
+C -1 ; WX 556 ; N aacute ; B 44 -15 542 699 ;
+C -1 ; WX 737 ; N registered ; B -8 -15 744 737 ;
+C -1 ; WX 315 ; N icircumflex ; B 1 0 314 695 ;
+C -1 ; WX 611 ; N udieresis ; B 22 -15 589 645 ;
+C -1 ; WX 500 ; N ograve ; B 34 -15 466 699 ;
+C -1 ; WX 611 ; N uacute ; B 22 -15 589 699 ;
+C -1 ; WX 611 ; N ucircumflex ; B 22 -15 589 695 ;
+C -1 ; WX 722 ; N Aacute ; B -8 0 730 937 ;
+C -1 ; WX 315 ; N igrave ; B 8 0 286 699 ;
+C -1 ; WX 407 ; N Icircumflex ; B 38 0 369 933 ;
+C -1 ; WX 444 ; N ccedilla ; B 34 -215 426 479 ;
+C -1 ; WX 556 ; N adieresis ; B 44 -15 542 645 ;
+C -1 ; WX 722 ; N Ecircumflex ; B 29 0 663 933 ;
+C -1 ; WX 463 ; N scaron ; B 46 -15 417 695 ;
+C -1 ; WX 574 ; N thorn ; B 22 -205 540 737 ;
+C -1 ; WX 1000 ; N trademark ; B 32 318 968 722 ;
+C -1 ; WX 500 ; N egrave ; B 34 -15 466 699 ;
+C -1 ; WX 333 ; N threesuperior ; B 18 273 315 705 ;
+C -1 ; WX 481 ; N zcaron ; B 42 0 439 695 ;
+C -1 ; WX 556 ; N atilde ; B 44 -15 542 655 ;
+C -1 ; WX 556 ; N aring ; B 44 -15 542 732 ;
+C -1 ; WX 500 ; N ocircumflex ; B 34 -15 466 695 ;
+C -1 ; WX 722 ; N Edieresis ; B 29 0 663 883 ;
+C -1 ; WX 834 ; N threequarters ; B 28 -15 795 705 ;
+C -1 ; WX 537 ; N ydieresis ; B 4 -205 533 645 ;
+C -1 ; WX 537 ; N yacute ; B 4 -205 533 699 ;
+C -1 ; WX 315 ; N iacute ; B 18 0 307 699 ;
+C -1 ; WX 722 ; N Acircumflex ; B -8 0 730 933 ;
+C -1 ; WX 815 ; N Uacute ; B 16 -15 799 937 ;
+C -1 ; WX 500 ; N eacute ; B 34 -15 466 699 ;
+C -1 ; WX 778 ; N Ograve ; B 45 -15 733 937 ;
+C -1 ; WX 556 ; N agrave ; B 44 -15 542 699 ;
+C -1 ; WX 815 ; N Udieresis ; B 16 -15 799 883 ;
+C -1 ; WX 556 ; N acircumflex ; B 44 -15 542 695 ;
+C -1 ; WX 407 ; N Igrave ; B 38 0 369 937 ;
+C -1 ; WX 333 ; N twosuperior ; B 14 282 319 705 ;
+C -1 ; WX 815 ; N Ugrave ; B 16 -15 799 937 ;
+C -1 ; WX 834 ; N onequarter ; B 39 -15 795 705 ;
+C -1 ; WX 815 ; N Ucircumflex ; B 16 -15 799 933 ;
+C -1 ; WX 630 ; N Scaron ; B 47 -15 583 933 ;
+C -1 ; WX 407 ; N Idieresis ; B 38 0 369 883 ;
+C -1 ; WX 315 ; N idieresis ; B 7 0 308 645 ;
+C -1 ; WX 722 ; N Egrave ; B 29 0 663 937 ;
+C -1 ; WX 778 ; N Oacute ; B 45 -15 733 937 ;
+C -1 ; WX 606 ; N divide ; B 50 -22 556 528 ;
+C -1 ; WX 722 ; N Atilde ; B -8 0 730 893 ;
+C -1 ; WX 722 ; N Aring ; B -8 0 730 965 ;
+C -1 ; WX 778 ; N Odieresis ; B 45 -15 733 883 ;
+C -1 ; WX 722 ; N Adieresis ; B -8 0 730 883 ;
+C -1 ; WX 815 ; N Ntilde ; B 24 -15 791 893 ;
+C -1 ; WX 611 ; N Zcaron ; B 24 0 576 933 ;
+C -1 ; WX 667 ; N Thorn ; B 29 0 650 722 ;
+C -1 ; WX 407 ; N Iacute ; B 38 0 369 937 ;
+C -1 ; WX 606 ; N plusminus ; B 50 0 556 506 ;
+C -1 ; WX 606 ; N multiply ; B 74 24 532 482 ;
+C -1 ; WX 722 ; N Eacute ; B 29 0 663 937 ;
+C -1 ; WX 704 ; N Ydieresis ; B -11 0 715 883 ;
+C -1 ; WX 333 ; N onesuperior ; B 39 282 294 705 ;
+C -1 ; WX 611 ; N ugrave ; B 22 -15 589 699 ;
+C -1 ; WX 606 ; N logicalnot ; B 50 108 556 389 ;
+C -1 ; WX 611 ; N ntilde ; B 22 0 589 655 ;
+C -1 ; WX 778 ; N Otilde ; B 45 -15 733 893 ;
+C -1 ; WX 500 ; N otilde ; B 34 -15 466 655 ;
+C -1 ; WX 722 ; N Ccedilla ; B 45 -215 668 737 ;
+C -1 ; WX 722 ; N Agrave ; B -8 0 730 937 ;
+C -1 ; WX 834 ; N onehalf ; B 39 -15 820 705 ;
+C -1 ; WX 778 ; N Eth ; B 29 0 733 722 ;
+C -1 ; WX 400 ; N degree ; B 57 419 343 705 ;
+C -1 ; WX 704 ; N Yacute ; B -11 0 715 937 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 45 -15 733 933 ;
+C -1 ; WX 500 ; N oacute ; B 34 -15 466 699 ;
+C -1 ; WX 611 ; N mu ; B 22 -205 589 464 ;
+C -1 ; WX 606 ; N minus ; B 50 217 556 289 ;
+C -1 ; WX 500 ; N eth ; B 34 -15 466 752 ;
+C -1 ; WX 500 ; N odieresis ; B 34 -15 466 645 ;
+C -1 ; WX 737 ; N copyright ; B -8 -15 744 737 ;
+C -1 ; WX 606 ; N brokenbar ; B 267 -175 339 675 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 169
+
+KPX A y -37
+KPX A w -25
+KPX A v -37
+KPX A quoteright -74
+KPX A quotedblright -74
+KPX A Y -75
+KPX A W -50
+KPX A V -75
+KPX A U -30
+KPX A T -18
+
+KPX B period -37
+KPX B comma -37
+KPX B A -18
+
+KPX C period -37
+KPX C comma -37
+KPX C A -18
+
+KPX D period -37
+KPX D comma -37
+KPX D Y -18
+KPX D V -18
+
+KPX F r -10
+KPX F period -125
+KPX F o -55
+KPX F i -10
+KPX F e -55
+KPX F comma -125
+KPX F a -65
+KPX F A -50
+
+KPX G period -37
+KPX G comma -37
+
+KPX J u -25
+KPX J period -74
+KPX J o -25
+KPX J e -25
+KPX J comma -74
+KPX J a -25
+KPX J A -18
+
+KPX K y -25
+KPX K o 10
+KPX K e 10
+
+KPX L y -25
+KPX L quoteright -100
+KPX L quotedblright -100
+KPX L Y -74
+KPX L W -74
+KPX L V -91
+KPX L T -75
+
+KPX N period -55
+KPX N comma -55
+
+KPX O period -37
+KPX O comma -37
+KPX O Y -18
+KPX O V -18
+KPX O T 10
+
+KPX P period -125
+KPX P o -37
+KPX P e -37
+KPX P comma -125
+KPX P a -37
+KPX P A -55
+
+KPX Q period -25
+KPX Q comma -25
+
+KPX S period -37
+KPX S comma -37
+
+KPX T semicolon -37
+KPX T period -125
+KPX T o -55
+KPX T hyphen -100
+KPX T e -55
+KPX T comma -125
+KPX T colon -37
+KPX T a -55
+KPX T O 10
+KPX T A -18
+
+KPX U period -100
+KPX U comma -100
+KPX U A -30
+
+KPX V u -75
+KPX V semicolon -75
+KPX V period -125
+KPX V o -75
+KPX V i -18
+KPX V hyphen -100
+KPX V e -75
+KPX V comma -125
+KPX V colon -75
+KPX V a -85
+KPX V O -18
+KPX V A -74
+
+KPX W y -55
+KPX W u -55
+KPX W semicolon -100
+KPX W period -125
+KPX W o -60
+KPX W i -18
+KPX W hyphen -100
+KPX W e -60
+KPX W comma -125
+KPX W colon -100
+KPX W a -75
+KPX W A -50
+
+KPX Y u -91
+KPX Y semicolon -75
+KPX Y period -100
+KPX Y o -100
+KPX Y i -18
+KPX Y hyphen -125
+KPX Y e -100
+KPX Y comma -100
+KPX Y colon -75
+KPX Y a -100
+KPX Y O -18
+KPX Y A -75
+
+KPX a y -10
+KPX a w -10
+KPX a v -10
+
+KPX b period -18
+KPX b comma -18
+
+KPX c period -18
+KPX c l -7
+KPX c k -7
+KPX c h -7
+KPX c comma -18
+
+KPX colon space -37
+
+KPX comma space -37
+KPX comma quoteright -37
+KPX comma quotedblright -37
+
+KPX e period -18
+KPX e comma -18
+
+KPX f quoteright 100
+KPX f quotedblright 100
+KPX f period -37
+KPX f comma -37
+
+KPX g period -25
+KPX g comma -25
+
+KPX o period -18
+KPX o comma -18
+
+KPX p period -18
+KPX p comma -18
+
+KPX period space -37
+KPX period quoteright -37
+KPX period quotedblright -37
+
+KPX quotedblleft A -74
+
+KPX quotedblright space -37
+
+KPX quoteleft quoteleft -25
+KPX quoteleft A -74
+
+KPX quoteright s -25
+KPX quoteright quoteright -25
+KPX quoteright d -37
+
+KPX r period -100
+KPX r hyphen -37
+KPX r comma -100
+
+KPX s period -25
+KPX s comma -25
+
+KPX semicolon space -37
+
+KPX space quoteleft -37
+KPX space quotedblleft -37
+KPX space Y -37
+KPX space W -37
+KPX space V -37
+KPX space T -37
+KPX space A -37
+
+KPX v period -125
+KPX v comma -125
+
+KPX w period -125
+KPX w comma -125
+KPX w a -18
+
+KPX y period -125
+KPX y comma -125
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 238 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 238 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 238 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 238 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 195 243 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 238 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 195 238 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 195 238 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 195 238 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 195 238 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 37 238 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 37 238 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 37 238 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 37 238 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 241 238 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 238 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 238 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 238 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 238 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 238 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 149 238 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 241 238 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 241 238 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 241 238 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 241 238 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 216 238 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 186 238 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 238 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 112 10 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 84 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 84 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 84 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 84 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -9 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -9 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -9 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -9 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 65 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 139 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 139 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 102 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 102 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 74 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Palatino-Bold.afm b/tlt3.0/library/afm/Palatino-Bold.afm
new file mode 100644
index 0000000..de147f7
--- /dev/null
+++ b/tlt3.0/library/afm/Palatino-Bold.afm
@@ -0,0 +1,435 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jul 2 22:26:30 1990
+Comment UniqueID 31793
+Comment VMusage 36031 46923
+FontName Palatino-Bold
+FullName Palatino Bold
+FamilyName Palatino
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -152 -266 1000 924
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.005
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Palatino is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 471
+Ascender 720
+Descender -258
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 63 -12 219 688 ;
+C 34 ; WX 402 ; N quotedbl ; B 22 376 380 695 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 496 673 ;
+C 36 ; WX 500 ; N dollar ; B 28 -114 472 721 ;
+C 37 ; WX 889 ; N percent ; B 61 -9 828 714 ;
+C 38 ; WX 833 ; N ampersand ; B 52 -17 813 684 ;
+C 39 ; WX 278 ; N quoteright ; B 29 405 249 695 ;
+C 40 ; WX 333 ; N parenleft ; B 65 -104 305 723 ;
+C 41 ; WX 333 ; N parenright ; B 28 -104 268 723 ;
+C 42 ; WX 444 ; N asterisk ; B 44 332 399 695 ;
+C 43 ; WX 606 ; N plus ; B 51 0 555 505 ;
+C 44 ; WX 250 ; N comma ; B -6 -166 227 141 ;
+C 45 ; WX 333 ; N hyphen ; B 16 195 317 305 ;
+C 46 ; WX 250 ; N period ; B 47 -12 203 144 ;
+C 47 ; WX 296 ; N slash ; B -9 -17 305 720 ;
+C 48 ; WX 500 ; N zero ; B 33 -17 468 660 ;
+C 49 ; WX 500 ; N one ; B 35 -3 455 670 ;
+C 50 ; WX 500 ; N two ; B 25 -3 472 660 ;
+C 51 ; WX 500 ; N three ; B 22 -17 458 660 ;
+C 52 ; WX 500 ; N four ; B 12 -3 473 672 ;
+C 53 ; WX 500 ; N five ; B 42 -17 472 656 ;
+C 54 ; WX 500 ; N six ; B 37 -17 469 660 ;
+C 55 ; WX 500 ; N seven ; B 46 -3 493 656 ;
+C 56 ; WX 500 ; N eight ; B 34 -17 467 660 ;
+C 57 ; WX 500 ; N nine ; B 31 -17 463 660 ;
+C 58 ; WX 250 ; N colon ; B 47 -12 203 454 ;
+C 59 ; WX 250 ; N semicolon ; B -6 -166 227 454 ;
+C 60 ; WX 606 ; N less ; B 49 -15 558 519 ;
+C 61 ; WX 606 ; N equal ; B 51 114 555 396 ;
+C 62 ; WX 606 ; N greater ; B 49 -15 558 519 ;
+C 63 ; WX 444 ; N question ; B 43 -12 411 687 ;
+C 64 ; WX 747 ; N at ; B 42 -12 704 681 ;
+C 65 ; WX 778 ; N A ; B 24 -3 757 686 ;
+C 66 ; WX 667 ; N B ; B 39 -3 611 681 ;
+C 67 ; WX 722 ; N C ; B 44 -17 695 695 ;
+C 68 ; WX 833 ; N D ; B 35 -3 786 681 ;
+C 69 ; WX 611 ; N E ; B 39 -4 577 681 ;
+C 70 ; WX 556 ; N F ; B 28 -3 539 681 ;
+C 71 ; WX 833 ; N G ; B 47 -17 776 695 ;
+C 72 ; WX 833 ; N H ; B 36 -3 796 681 ;
+C 73 ; WX 389 ; N I ; B 39 -3 350 681 ;
+C 74 ; WX 389 ; N J ; B -11 -213 350 681 ;
+C 75 ; WX 778 ; N K ; B 39 -3 763 681 ;
+C 76 ; WX 611 ; N L ; B 39 -4 577 681 ;
+C 77 ; WX 1000 ; N M ; B 32 -10 968 681 ;
+C 78 ; WX 833 ; N N ; B 35 -16 798 681 ;
+C 79 ; WX 833 ; N O ; B 47 -17 787 695 ;
+C 80 ; WX 611 ; N P ; B 39 -3 594 681 ;
+C 81 ; WX 833 ; N Q ; B 47 -184 787 695 ;
+C 82 ; WX 722 ; N R ; B 39 -3 708 681 ;
+C 83 ; WX 611 ; N S ; B 57 -17 559 695 ;
+C 84 ; WX 667 ; N T ; B 17 -3 650 681 ;
+C 85 ; WX 778 ; N U ; B 26 -17 760 681 ;
+C 86 ; WX 778 ; N V ; B 20 -3 763 681 ;
+C 87 ; WX 1000 ; N W ; B 17 -3 988 686 ;
+C 88 ; WX 667 ; N X ; B 17 -3 650 695 ;
+C 89 ; WX 667 ; N Y ; B 15 -3 660 695 ;
+C 90 ; WX 667 ; N Z ; B 24 -3 627 681 ;
+C 91 ; WX 333 ; N bracketleft ; B 73 -104 291 720 ;
+C 92 ; WX 606 ; N backslash ; B 72 0 534 720 ;
+C 93 ; WX 333 ; N bracketright ; B 42 -104 260 720 ;
+C 94 ; WX 606 ; N asciicircum ; B 52 275 554 678 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 29 405 249 695 ;
+C 97 ; WX 500 ; N a ; B 40 -17 478 471 ;
+C 98 ; WX 611 ; N b ; B 10 -17 556 720 ;
+C 99 ; WX 444 ; N c ; B 37 -17 414 471 ;
+C 100 ; WX 611 ; N d ; B 42 -17 577 720 ;
+C 101 ; WX 500 ; N e ; B 42 -17 461 471 ;
+C 102 ; WX 389 ; N f ; B 34 -3 381 720 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 26 -266 535 471 ;
+C 104 ; WX 611 ; N h ; B 24 -3 587 720 ;
+C 105 ; WX 333 ; N i ; B 34 -3 298 706 ;
+C 106 ; WX 333 ; N j ; B 3 -266 241 706 ;
+C 107 ; WX 611 ; N k ; B 21 -3 597 720 ;
+C 108 ; WX 333 ; N l ; B 24 -3 296 720 ;
+C 109 ; WX 889 ; N m ; B 24 -3 864 471 ;
+C 110 ; WX 611 ; N n ; B 24 -3 587 471 ;
+C 111 ; WX 556 ; N o ; B 40 -17 517 471 ;
+C 112 ; WX 611 ; N p ; B 29 -258 567 471 ;
+C 113 ; WX 611 ; N q ; B 52 -258 589 471 ;
+C 114 ; WX 389 ; N r ; B 30 -3 389 471 ;
+C 115 ; WX 444 ; N s ; B 39 -17 405 471 ;
+C 116 ; WX 333 ; N t ; B 22 -17 324 632 ;
+C 117 ; WX 611 ; N u ; B 25 -17 583 471 ;
+C 118 ; WX 556 ; N v ; B 11 -3 545 459 ;
+C 119 ; WX 833 ; N w ; B 13 -3 820 471 ;
+C 120 ; WX 500 ; N x ; B 20 -3 483 471 ;
+C 121 ; WX 556 ; N y ; B 10 -266 546 459 ;
+C 122 ; WX 500 ; N z ; B 16 -3 464 459 ;
+C 123 ; WX 310 ; N braceleft ; B 5 -117 288 725 ;
+C 124 ; WX 606 ; N bar ; B 260 0 346 720 ;
+C 125 ; WX 310 ; N braceright ; B 22 -117 305 725 ;
+C 126 ; WX 606 ; N asciitilde ; B 51 155 555 342 ;
+C 161 ; WX 278 ; N exclamdown ; B 59 -227 215 471 ;
+C 162 ; WX 500 ; N cent ; B 73 -106 450 554 ;
+C 163 ; WX 500 ; N sterling ; B -2 -19 501 676 ;
+C 164 ; WX 167 ; N fraction ; B -152 0 320 660 ;
+C 165 ; WX 500 ; N yen ; B 17 -3 483 695 ;
+C 166 ; WX 500 ; N florin ; B 11 -242 490 703 ;
+C 167 ; WX 500 ; N section ; B 30 -217 471 695 ;
+C 168 ; WX 500 ; N currency ; B 32 96 468 533 ;
+C 169 ; WX 227 ; N quotesingle ; B 45 376 181 695 ;
+C 170 ; WX 500 ; N quotedblleft ; B 34 405 466 695 ;
+C 171 ; WX 500 ; N guillemotleft ; B 36 44 463 438 ;
+C 172 ; WX 389 ; N guilsinglleft ; B 82 44 307 438 ;
+C 173 ; WX 389 ; N guilsinglright ; B 82 44 307 438 ;
+C 174 ; WX 611 ; N fi ; B 10 -3 595 720 ;
+C 175 ; WX 611 ; N fl ; B 17 -3 593 720 ;
+C 177 ; WX 500 ; N endash ; B 0 208 500 291 ;
+C 178 ; WX 500 ; N dagger ; B 29 -6 472 682 ;
+C 179 ; WX 500 ; N daggerdbl ; B 32 -245 468 682 ;
+C 180 ; WX 250 ; N periodcentered ; B 47 179 203 335 ;
+C 182 ; WX 641 ; N paragraph ; B 19 -161 599 683 ;
+C 183 ; WX 606 ; N bullet ; B 131 172 475 516 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 56 -160 276 130 ;
+C 185 ; WX 500 ; N quotedblbase ; B 34 -160 466 130 ;
+C 186 ; WX 500 ; N quotedblright ; B 34 405 466 695 ;
+C 187 ; WX 500 ; N guillemotright ; B 37 44 464 438 ;
+C 188 ; WX 1000 ; N ellipsis ; B 89 -12 911 144 ;
+C 189 ; WX 1000 ; N perthousand ; B 33 -9 982 724 ;
+C 191 ; WX 444 ; N questiondown ; B 33 -231 401 471 ;
+C 193 ; WX 333 ; N grave ; B 18 506 256 691 ;
+C 194 ; WX 333 ; N acute ; B 78 506 316 691 ;
+C 195 ; WX 333 ; N circumflex ; B -2 506 335 681 ;
+C 196 ; WX 333 ; N tilde ; B -16 535 349 661 ;
+C 197 ; WX 333 ; N macron ; B 1 538 332 609 ;
+C 198 ; WX 333 ; N breve ; B 15 506 318 669 ;
+C 199 ; WX 333 ; N dotaccent ; B 100 537 234 671 ;
+C 200 ; WX 333 ; N dieresis ; B -8 537 341 671 ;
+C 202 ; WX 333 ; N ring ; B 67 500 267 700 ;
+C 203 ; WX 333 ; N cedilla ; B 73 -225 300 -7 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -56 506 390 691 ;
+C 206 ; WX 333 ; N ogonek ; B 60 -246 274 -17 ;
+C 207 ; WX 333 ; N caron ; B -2 510 335 685 ;
+C 208 ; WX 1000 ; N emdash ; B 0 208 1000 291 ;
+C 225 ; WX 1000 ; N AE ; B 12 -4 954 681 ;
+C 227 ; WX 438 ; N ordfeminine ; B 77 367 361 660 ;
+C 232 ; WX 611 ; N Lslash ; B 16 -4 577 681 ;
+C 233 ; WX 833 ; N Oslash ; B 32 -20 808 698 ;
+C 234 ; WX 1000 ; N OE ; B 43 -17 985 695 ;
+C 235 ; WX 488 ; N ordmasculine ; B 89 367 399 660 ;
+C 241 ; WX 778 ; N ae ; B 46 -17 731 471 ;
+C 245 ; WX 333 ; N dotlessi ; B 34 -3 298 471 ;
+C 248 ; WX 333 ; N lslash ; B -4 -3 334 720 ;
+C 249 ; WX 556 ; N oslash ; B 23 -18 534 471 ;
+C 250 ; WX 833 ; N oe ; B 48 -17 799 471 ;
+C 251 ; WX 611 ; N germandbls ; B 30 -17 565 720 ;
+C -1 ; WX 667 ; N Zcaron ; B 24 -3 627 909 ;
+C -1 ; WX 444 ; N ccedilla ; B 37 -225 414 471 ;
+C -1 ; WX 556 ; N ydieresis ; B 10 -266 546 691 ;
+C -1 ; WX 500 ; N atilde ; B 40 -17 478 673 ;
+C -1 ; WX 333 ; N icircumflex ; B -2 -3 335 701 ;
+C -1 ; WX 300 ; N threesuperior ; B 9 261 292 667 ;
+C -1 ; WX 500 ; N ecircumflex ; B 42 -17 461 701 ;
+C -1 ; WX 611 ; N thorn ; B 17 -258 563 720 ;
+C -1 ; WX 500 ; N egrave ; B 42 -17 461 711 ;
+C -1 ; WX 300 ; N twosuperior ; B 5 261 295 660 ;
+C -1 ; WX 500 ; N eacute ; B 42 -17 461 711 ;
+C -1 ; WX 556 ; N otilde ; B 40 -17 517 673 ;
+C -1 ; WX 778 ; N Aacute ; B 24 -3 757 915 ;
+C -1 ; WX 556 ; N ocircumflex ; B 40 -17 517 701 ;
+C -1 ; WX 556 ; N yacute ; B 10 -266 546 711 ;
+C -1 ; WX 611 ; N udieresis ; B 25 -17 583 691 ;
+C -1 ; WX 750 ; N threequarters ; B 15 -2 735 667 ;
+C -1 ; WX 500 ; N acircumflex ; B 40 -17 478 701 ;
+C -1 ; WX 833 ; N Eth ; B 10 -3 786 681 ;
+C -1 ; WX 500 ; N edieresis ; B 42 -17 461 691 ;
+C -1 ; WX 611 ; N ugrave ; B 25 -17 583 711 ;
+C -1 ; WX 998 ; N trademark ; B 38 274 961 678 ;
+C -1 ; WX 556 ; N ograve ; B 40 -17 517 711 ;
+C -1 ; WX 444 ; N scaron ; B 39 -17 405 693 ;
+C -1 ; WX 389 ; N Idieresis ; B 20 -3 369 895 ;
+C -1 ; WX 611 ; N uacute ; B 25 -17 583 711 ;
+C -1 ; WX 500 ; N agrave ; B 40 -17 478 711 ;
+C -1 ; WX 611 ; N ntilde ; B 24 -3 587 673 ;
+C -1 ; WX 500 ; N aring ; B 40 -17 478 700 ;
+C -1 ; WX 500 ; N zcaron ; B 16 -3 464 693 ;
+C -1 ; WX 389 ; N Icircumflex ; B 26 -3 363 905 ;
+C -1 ; WX 833 ; N Ntilde ; B 35 -16 798 885 ;
+C -1 ; WX 611 ; N ucircumflex ; B 25 -17 583 701 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 39 -4 577 905 ;
+C -1 ; WX 389 ; N Iacute ; B 39 -3 350 915 ;
+C -1 ; WX 722 ; N Ccedilla ; B 44 -225 695 695 ;
+C -1 ; WX 833 ; N Odieresis ; B 47 -17 787 895 ;
+C -1 ; WX 611 ; N Scaron ; B 57 -17 559 909 ;
+C -1 ; WX 611 ; N Edieresis ; B 39 -4 577 895 ;
+C -1 ; WX 389 ; N Igrave ; B 39 -3 350 915 ;
+C -1 ; WX 500 ; N adieresis ; B 40 -17 478 691 ;
+C -1 ; WX 833 ; N Ograve ; B 47 -17 787 915 ;
+C -1 ; WX 611 ; N Egrave ; B 39 -4 577 915 ;
+C -1 ; WX 667 ; N Ydieresis ; B 15 -3 660 895 ;
+C -1 ; WX 747 ; N registered ; B 26 -17 720 695 ;
+C -1 ; WX 833 ; N Otilde ; B 47 -17 787 885 ;
+C -1 ; WX 750 ; N onequarter ; B 19 -2 735 665 ;
+C -1 ; WX 778 ; N Ugrave ; B 26 -17 760 915 ;
+C -1 ; WX 778 ; N Ucircumflex ; B 26 -17 760 905 ;
+C -1 ; WX 611 ; N Thorn ; B 39 -3 574 681 ;
+C -1 ; WX 606 ; N divide ; B 51 0 555 510 ;
+C -1 ; WX 778 ; N Atilde ; B 24 -3 757 885 ;
+C -1 ; WX 778 ; N Uacute ; B 26 -17 760 915 ;
+C -1 ; WX 833 ; N Ocircumflex ; B 47 -17 787 905 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 114 555 396 ;
+C -1 ; WX 778 ; N Aring ; B 24 -3 757 924 ;
+C -1 ; WX 333 ; N idieresis ; B -8 -3 341 691 ;
+C -1 ; WX 333 ; N iacute ; B 34 -3 316 711 ;
+C -1 ; WX 500 ; N aacute ; B 40 -17 478 711 ;
+C -1 ; WX 606 ; N plusminus ; B 51 0 555 505 ;
+C -1 ; WX 606 ; N multiply ; B 72 21 534 483 ;
+C -1 ; WX 778 ; N Udieresis ; B 26 -17 760 895 ;
+C -1 ; WX 606 ; N minus ; B 51 212 555 298 ;
+C -1 ; WX 300 ; N onesuperior ; B 14 261 287 665 ;
+C -1 ; WX 611 ; N Eacute ; B 39 -4 577 915 ;
+C -1 ; WX 778 ; N Acircumflex ; B 24 -3 757 905 ;
+C -1 ; WX 747 ; N copyright ; B 26 -17 720 695 ;
+C -1 ; WX 778 ; N Agrave ; B 24 -3 757 915 ;
+C -1 ; WX 556 ; N odieresis ; B 40 -17 517 691 ;
+C -1 ; WX 556 ; N oacute ; B 40 -17 517 711 ;
+C -1 ; WX 400 ; N degree ; B 50 360 350 660 ;
+C -1 ; WX 333 ; N igrave ; B 18 -3 298 711 ;
+C -1 ; WX 611 ; N mu ; B 25 -225 583 471 ;
+C -1 ; WX 833 ; N Oacute ; B 47 -17 787 915 ;
+C -1 ; WX 556 ; N eth ; B 40 -17 517 720 ;
+C -1 ; WX 778 ; N Adieresis ; B 24 -3 757 895 ;
+C -1 ; WX 667 ; N Yacute ; B 15 -3 660 915 ;
+C -1 ; WX 606 ; N brokenbar ; B 260 0 346 720 ;
+C -1 ; WX 750 ; N onehalf ; B 9 -2 745 665 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 101
+
+KPX A y -70
+KPX A w -70
+KPX A v -70
+KPX A space -18
+KPX A quoteright -92
+KPX A Y -111
+KPX A W -90
+KPX A V -129
+KPX A T -92
+
+KPX F period -111
+KPX F comma -111
+KPX F A -55
+
+KPX L y -74
+KPX L space -18
+KPX L quoteright -74
+KPX L Y -92
+KPX L W -92
+KPX L V -92
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -74
+
+KPX R y -30
+KPX R Y -55
+KPX R W -37
+KPX R V -74
+KPX R T -55
+
+KPX T y -90
+KPX T w -90
+KPX T u -129
+KPX T semicolon -74
+KPX T s -111
+KPX T r -111
+KPX T period -92
+KPX T o -111
+KPX T i -55
+KPX T hyphen -92
+KPX T e -111
+KPX T comma -92
+KPX T colon -74
+KPX T c -129
+KPX T a -111
+KPX T A -92
+
+KPX V y -90
+KPX V u -92
+KPX V semicolon -74
+KPX V r -111
+KPX V period -129
+KPX V o -111
+KPX V i -55
+KPX V hyphen -92
+KPX V e -111
+KPX V comma -129
+KPX V colon -74
+KPX V a -111
+KPX V A -129
+
+KPX W y -74
+KPX W u -74
+KPX W semicolon -37
+KPX W r -74
+KPX W period -37
+KPX W o -74
+KPX W i -37
+KPX W hyphen -37
+KPX W e -74
+KPX W comma -92
+KPX W colon -37
+KPX W a -74
+KPX W A -90
+
+KPX Y v -74
+KPX Y u -74
+KPX Y semicolon -55
+KPX Y q -92
+KPX Y period -74
+KPX Y p -74
+KPX Y o -74
+KPX Y i -55
+KPX Y hyphen -74
+KPX Y e -74
+KPX Y comma -74
+KPX Y colon -55
+KPX Y a -74
+KPX Y A -55
+
+KPX f quoteright 37
+KPX f f -18
+
+KPX one one -37
+
+KPX quoteleft quoteleft -55
+
+KPX quoteright t -18
+KPX quoteright space -55
+KPX quoteright s -55
+KPX quoteright quoteright -55
+
+KPX r quoteright 55
+KPX r period -55
+KPX r hyphen -18
+KPX r comma -55
+
+KPX v period -111
+KPX v comma -111
+
+KPX w period -92
+KPX w comma -92
+
+KPX y period -92
+KPX y comma -92
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 223 224 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 211 224 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 223 224 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 215 224 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 223 224 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 223 224 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 195 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 139 224 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 139 224 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 139 224 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 139 224 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 28 224 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 28 224 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 28 224 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 28 224 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 250 224 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 250 224 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 250 224 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 250 224 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 250 224 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 250 224 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 139 224 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 235 224 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 235 224 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 235 224 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 223 224 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 211 224 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 199 224 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 167 224 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 20 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 84 20 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 84 20 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 84 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 12 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 84 20 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 96 20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 92 20 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 84 20 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 20 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex 0 20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis 0 20 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 20 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 139 12 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 112 20 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 112 20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 20 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 112 20 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 12 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 56 8 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 151 20 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 139 20 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 139 20 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 131 20 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 144 20 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 124 20 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 8 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Palatino-BoldItalic.afm b/tlt3.0/library/afm/Palatino-BoldItalic.afm
new file mode 100644
index 0000000..44c7b2c
--- /dev/null
+++ b/tlt3.0/library/afm/Palatino-BoldItalic.afm
@@ -0,0 +1,442 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jul 2 22:48:39 1990
+Comment UniqueID 31799
+Comment VMusage 37656 48548
+FontName Palatino-BoldItalic
+FullName Palatino Bold Italic
+FamilyName Palatino
+Weight Bold
+ItalicAngle -10
+IsFixedPitch false
+FontBBox -170 -271 1073 926
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.005
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Palatino is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 681
+XHeight 469
+Ascender 726
+Descender -271
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 58 -17 322 695 ;
+C 34 ; WX 500 ; N quotedbl ; B 137 467 493 720 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 496 673 ;
+C 36 ; WX 500 ; N dollar ; B 20 -108 477 737 ;
+C 37 ; WX 889 ; N percent ; B 56 -17 790 697 ;
+C 38 ; WX 833 ; N ampersand ; B 74 -17 811 695 ;
+C 39 ; WX 278 ; N quoteright ; B 76 431 302 720 ;
+C 40 ; WX 333 ; N parenleft ; B 58 -129 368 723 ;
+C 41 ; WX 333 ; N parenright ; B -12 -129 298 723 ;
+C 42 ; WX 444 ; N asterisk ; B 84 332 439 695 ;
+C 43 ; WX 606 ; N plus ; B 50 -5 556 501 ;
+C 44 ; WX 250 ; N comma ; B -33 -164 208 147 ;
+C 45 ; WX 389 ; N hyphen ; B 37 198 362 300 ;
+C 46 ; WX 250 ; N period ; B 48 -17 187 135 ;
+C 47 ; WX 315 ; N slash ; B 1 -17 315 720 ;
+C 48 ; WX 500 ; N zero ; B 42 -17 490 683 ;
+C 49 ; WX 500 ; N one ; B 41 -3 434 678 ;
+C 50 ; WX 500 ; N two ; B 1 -3 454 683 ;
+C 51 ; WX 500 ; N three ; B 8 -17 450 683 ;
+C 52 ; WX 500 ; N four ; B 3 -3 487 683 ;
+C 53 ; WX 500 ; N five ; B 14 -17 481 675 ;
+C 54 ; WX 500 ; N six ; B 39 -17 488 683 ;
+C 55 ; WX 500 ; N seven ; B 69 -3 544 674 ;
+C 56 ; WX 500 ; N eight ; B 26 -17 484 683 ;
+C 57 ; WX 500 ; N nine ; B 27 -17 491 683 ;
+C 58 ; WX 250 ; N colon ; B 38 -17 236 452 ;
+C 59 ; WX 250 ; N semicolon ; B -33 -164 247 452 ;
+C 60 ; WX 606 ; N less ; B 49 -21 558 517 ;
+C 61 ; WX 606 ; N equal ; B 51 106 555 390 ;
+C 62 ; WX 606 ; N greater ; B 48 -21 557 517 ;
+C 63 ; WX 444 ; N question ; B 91 -17 450 695 ;
+C 64 ; WX 833 ; N at ; B 82 -12 744 681 ;
+C 65 ; WX 722 ; N A ; B -35 -3 685 683 ;
+C 66 ; WX 667 ; N B ; B 8 -3 629 681 ;
+C 67 ; WX 685 ; N C ; B 69 -17 695 695 ;
+C 68 ; WX 778 ; N D ; B 0 -3 747 682 ;
+C 69 ; WX 611 ; N E ; B 11 -3 606 681 ;
+C 70 ; WX 556 ; N F ; B -6 -3 593 681 ;
+C 71 ; WX 778 ; N G ; B 72 -17 750 695 ;
+C 72 ; WX 778 ; N H ; B -12 -3 826 681 ;
+C 73 ; WX 389 ; N I ; B -1 -3 412 681 ;
+C 74 ; WX 389 ; N J ; B -29 -207 417 681 ;
+C 75 ; WX 722 ; N K ; B -10 -3 746 681 ;
+C 76 ; WX 611 ; N L ; B 26 -3 578 681 ;
+C 77 ; WX 944 ; N M ; B -23 -17 985 681 ;
+C 78 ; WX 778 ; N N ; B -2 -3 829 681 ;
+C 79 ; WX 833 ; N O ; B 76 -17 794 695 ;
+C 80 ; WX 667 ; N P ; B 11 -3 673 681 ;
+C 81 ; WX 833 ; N Q ; B 76 -222 794 695 ;
+C 82 ; WX 722 ; N R ; B 4 -3 697 681 ;
+C 83 ; WX 556 ; N S ; B 50 -17 517 695 ;
+C 84 ; WX 611 ; N T ; B 56 -3 674 681 ;
+C 85 ; WX 778 ; N U ; B 83 -17 825 681 ;
+C 86 ; WX 667 ; N V ; B 67 -3 745 681 ;
+C 87 ; WX 1000 ; N W ; B 67 -3 1073 689 ;
+C 88 ; WX 722 ; N X ; B -9 -3 772 681 ;
+C 89 ; WX 611 ; N Y ; B 54 -3 675 695 ;
+C 90 ; WX 667 ; N Z ; B 1 -3 676 681 ;
+C 91 ; WX 333 ; N bracketleft ; B 45 -102 381 723 ;
+C 92 ; WX 606 ; N backslash ; B 72 0 534 720 ;
+C 93 ; WX 333 ; N bracketright ; B -21 -102 315 723 ;
+C 94 ; WX 606 ; N asciicircum ; B 63 275 543 678 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 65 431 291 720 ;
+C 97 ; WX 556 ; N a ; B 44 -17 519 470 ;
+C 98 ; WX 537 ; N b ; B 44 -17 494 726 ;
+C 99 ; WX 444 ; N c ; B 32 -17 436 469 ;
+C 100 ; WX 556 ; N d ; B 38 -17 550 726 ;
+C 101 ; WX 444 ; N e ; B 28 -17 418 469 ;
+C 102 ; WX 333 ; N f ; B -130 -271 449 726 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B -50 -271 529 469 ;
+C 104 ; WX 556 ; N h ; B 22 -17 522 726 ;
+C 105 ; WX 333 ; N i ; B 26 -17 312 695 ;
+C 106 ; WX 333 ; N j ; B -64 -271 323 695 ;
+C 107 ; WX 556 ; N k ; B 34 -17 528 726 ;
+C 108 ; WX 333 ; N l ; B 64 -17 318 726 ;
+C 109 ; WX 833 ; N m ; B 19 -17 803 469 ;
+C 110 ; WX 556 ; N n ; B 17 -17 521 469 ;
+C 111 ; WX 556 ; N o ; B 48 -17 502 469 ;
+C 112 ; WX 556 ; N p ; B -21 -271 516 469 ;
+C 113 ; WX 537 ; N q ; B 32 -271 513 469 ;
+C 114 ; WX 389 ; N r ; B 20 -17 411 469 ;
+C 115 ; WX 444 ; N s ; B 25 -17 406 469 ;
+C 116 ; WX 389 ; N t ; B 42 -17 409 636 ;
+C 117 ; WX 556 ; N u ; B 22 -17 521 469 ;
+C 118 ; WX 556 ; N v ; B 19 -17 513 469 ;
+C 119 ; WX 833 ; N w ; B 27 -17 802 469 ;
+C 120 ; WX 500 ; N x ; B -8 -17 500 469 ;
+C 121 ; WX 556 ; N y ; B 13 -271 541 469 ;
+C 122 ; WX 500 ; N z ; B 31 -17 470 469 ;
+C 123 ; WX 333 ; N braceleft ; B 18 -105 334 720 ;
+C 124 ; WX 606 ; N bar ; B 259 0 347 720 ;
+C 125 ; WX 333 ; N braceright ; B -1 -105 315 720 ;
+C 126 ; WX 606 ; N asciitilde ; B 51 151 555 346 ;
+C 161 ; WX 333 ; N exclamdown ; B 2 -225 259 479 ;
+C 162 ; WX 500 ; N cent ; B 52 -105 456 547 ;
+C 163 ; WX 500 ; N sterling ; B 21 -5 501 683 ;
+C 164 ; WX 167 ; N fraction ; B -170 0 338 683 ;
+C 165 ; WX 500 ; N yen ; B 11 -3 538 695 ;
+C 166 ; WX 500 ; N florin ; B 8 -242 479 690 ;
+C 167 ; WX 556 ; N section ; B 47 -151 497 695 ;
+C 168 ; WX 500 ; N currency ; B 32 96 468 533 ;
+C 169 ; WX 250 ; N quotesingle ; B 127 467 293 720 ;
+C 170 ; WX 500 ; N quotedblleft ; B 65 431 511 720 ;
+C 171 ; WX 500 ; N guillemotleft ; B 35 43 458 446 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 60 43 292 446 ;
+C 173 ; WX 333 ; N guilsinglright ; B 35 40 267 443 ;
+C 174 ; WX 611 ; N fi ; B -130 -271 588 726 ;
+C 175 ; WX 611 ; N fl ; B -130 -271 631 726 ;
+C 177 ; WX 500 ; N endash ; B -12 214 512 282 ;
+C 178 ; WX 556 ; N dagger ; B 67 -3 499 685 ;
+C 179 ; WX 556 ; N daggerdbl ; B 33 -153 537 693 ;
+C 180 ; WX 250 ; N periodcentered ; B 67 172 206 324 ;
+C 182 ; WX 556 ; N paragraph ; B 14 -204 629 681 ;
+C 183 ; WX 606 ; N bullet ; B 131 172 475 516 ;
+C 184 ; WX 250 ; N quotesinglbase ; B -3 -144 220 145 ;
+C 185 ; WX 500 ; N quotedblbase ; B -18 -144 424 145 ;
+C 186 ; WX 500 ; N quotedblright ; B 73 431 519 720 ;
+C 187 ; WX 500 ; N guillemotright ; B 35 40 458 443 ;
+C 188 ; WX 1000 ; N ellipsis ; B 91 -17 896 135 ;
+C 189 ; WX 1000 ; N perthousand ; B 65 -17 912 691 ;
+C 191 ; WX 444 ; N questiondown ; B -12 -226 347 479 ;
+C 193 ; WX 333 ; N grave ; B 110 518 322 699 ;
+C 194 ; WX 333 ; N acute ; B 153 518 392 699 ;
+C 195 ; WX 333 ; N circumflex ; B 88 510 415 684 ;
+C 196 ; WX 333 ; N tilde ; B 82 535 441 654 ;
+C 197 ; WX 333 ; N macron ; B 76 538 418 608 ;
+C 198 ; WX 333 ; N breve ; B 96 518 412 680 ;
+C 199 ; WX 333 ; N dotaccent ; B 202 537 325 668 ;
+C 200 ; WX 333 ; N dieresis ; B 90 537 426 668 ;
+C 202 ; WX 556 ; N ring ; B 277 514 477 714 ;
+C 203 ; WX 333 ; N cedilla ; B 12 -218 248 5 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -28 518 409 699 ;
+C 206 ; WX 333 ; N ogonek ; B 32 -206 238 -17 ;
+C 207 ; WX 333 ; N caron ; B 113 510 445 684 ;
+C 208 ; WX 1000 ; N emdash ; B -12 214 1012 282 ;
+C 225 ; WX 944 ; N AE ; B -29 -3 927 681 ;
+C 227 ; WX 333 ; N ordfeminine ; B 47 391 355 684 ;
+C 232 ; WX 611 ; N Lslash ; B 6 -3 578 681 ;
+C 233 ; WX 833 ; N Oslash ; B 57 -54 797 730 ;
+C 234 ; WX 944 ; N OE ; B 39 -17 961 695 ;
+C 235 ; WX 333 ; N ordmasculine ; B 51 391 346 683 ;
+C 241 ; WX 738 ; N ae ; B 44 -17 711 469 ;
+C 245 ; WX 333 ; N dotlessi ; B 26 -17 293 469 ;
+C 248 ; WX 333 ; N lslash ; B 13 -17 365 726 ;
+C 249 ; WX 556 ; N oslash ; B 14 -50 522 506 ;
+C 250 ; WX 778 ; N oe ; B 48 -17 755 469 ;
+C 251 ; WX 556 ; N germandbls ; B -131 -271 549 726 ;
+C -1 ; WX 667 ; N Zcaron ; B 1 -3 676 896 ;
+C -1 ; WX 444 ; N ccedilla ; B 32 -218 436 469 ;
+C -1 ; WX 556 ; N ydieresis ; B 13 -271 541 688 ;
+C -1 ; WX 556 ; N atilde ; B 44 -17 553 666 ;
+C -1 ; WX 333 ; N icircumflex ; B 26 -17 403 704 ;
+C -1 ; WX 300 ; N threesuperior ; B 23 263 310 683 ;
+C -1 ; WX 444 ; N ecircumflex ; B 28 -17 471 704 ;
+C -1 ; WX 556 ; N thorn ; B -21 -271 516 726 ;
+C -1 ; WX 444 ; N egrave ; B 28 -17 418 719 ;
+C -1 ; WX 300 ; N twosuperior ; B 26 271 321 683 ;
+C -1 ; WX 444 ; N eacute ; B 28 -17 448 719 ;
+C -1 ; WX 556 ; N otilde ; B 48 -17 553 666 ;
+C -1 ; WX 722 ; N Aacute ; B -35 -3 685 911 ;
+C -1 ; WX 556 ; N ocircumflex ; B 48 -17 515 704 ;
+C -1 ; WX 556 ; N yacute ; B 13 -271 541 719 ;
+C -1 ; WX 556 ; N udieresis ; B 22 -17 538 688 ;
+C -1 ; WX 750 ; N threequarters ; B 18 -2 732 683 ;
+C -1 ; WX 556 ; N acircumflex ; B 44 -17 527 704 ;
+C -1 ; WX 778 ; N Eth ; B 0 -3 747 682 ;
+C -1 ; WX 444 ; N edieresis ; B 28 -17 482 688 ;
+C -1 ; WX 556 ; N ugrave ; B 22 -17 521 719 ;
+C -1 ; WX 1000 ; N trademark ; B 38 274 961 678 ;
+C -1 ; WX 556 ; N ograve ; B 48 -17 502 719 ;
+C -1 ; WX 444 ; N scaron ; B 25 -17 489 692 ;
+C -1 ; WX 389 ; N Idieresis ; B -1 -3 454 880 ;
+C -1 ; WX 556 ; N uacute ; B 22 -17 521 719 ;
+C -1 ; WX 556 ; N agrave ; B 44 -17 519 719 ;
+C -1 ; WX 556 ; N ntilde ; B 17 -17 553 666 ;
+C -1 ; WX 556 ; N aring ; B 44 -17 519 714 ;
+C -1 ; WX 500 ; N zcaron ; B 31 -17 517 692 ;
+C -1 ; WX 389 ; N Icircumflex ; B -1 -3 443 896 ;
+C -1 ; WX 778 ; N Ntilde ; B -2 -3 829 866 ;
+C -1 ; WX 556 ; N ucircumflex ; B 22 -17 521 704 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 11 -3 606 896 ;
+C -1 ; WX 389 ; N Iacute ; B -1 -3 420 911 ;
+C -1 ; WX 685 ; N Ccedilla ; B 69 -218 695 695 ;
+C -1 ; WX 833 ; N Odieresis ; B 76 -17 794 880 ;
+C -1 ; WX 556 ; N Scaron ; B 50 -17 557 896 ;
+C -1 ; WX 611 ; N Edieresis ; B 11 -3 606 880 ;
+C -1 ; WX 389 ; N Igrave ; B -1 -3 412 911 ;
+C -1 ; WX 556 ; N adieresis ; B 44 -17 538 688 ;
+C -1 ; WX 833 ; N Ograve ; B 76 -17 794 911 ;
+C -1 ; WX 611 ; N Egrave ; B 11 -3 606 911 ;
+C -1 ; WX 611 ; N Ydieresis ; B 54 -3 675 880 ;
+C -1 ; WX 747 ; N registered ; B 26 -17 720 695 ;
+C -1 ; WX 833 ; N Otilde ; B 76 -17 794 866 ;
+C -1 ; WX 750 ; N onequarter ; B 18 -2 732 683 ;
+C -1 ; WX 778 ; N Ugrave ; B 83 -17 825 911 ;
+C -1 ; WX 778 ; N Ucircumflex ; B 83 -17 825 896 ;
+C -1 ; WX 667 ; N Thorn ; B 11 -3 644 681 ;
+C -1 ; WX 606 ; N divide ; B 50 -5 556 501 ;
+C -1 ; WX 722 ; N Atilde ; B -35 -3 685 866 ;
+C -1 ; WX 778 ; N Uacute ; B 83 -17 825 911 ;
+C -1 ; WX 833 ; N Ocircumflex ; B 76 -17 794 896 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 107 555 390 ;
+C -1 ; WX 722 ; N Aring ; B -35 -3 685 926 ;
+C -1 ; WX 333 ; N idieresis ; B 26 -17 426 688 ;
+C -1 ; WX 333 ; N iacute ; B 26 -17 392 719 ;
+C -1 ; WX 556 ; N aacute ; B 44 -17 519 719 ;
+C -1 ; WX 606 ; N plusminus ; B 50 0 556 501 ;
+C -1 ; WX 606 ; N multiply ; B 72 17 534 479 ;
+C -1 ; WX 778 ; N Udieresis ; B 83 -17 825 880 ;
+C -1 ; WX 606 ; N minus ; B 51 204 555 292 ;
+C -1 ; WX 300 ; N onesuperior ; B 41 271 298 680 ;
+C -1 ; WX 611 ; N Eacute ; B 11 -3 606 911 ;
+C -1 ; WX 722 ; N Acircumflex ; B -35 -3 685 896 ;
+C -1 ; WX 747 ; N copyright ; B 26 -17 720 695 ;
+C -1 ; WX 722 ; N Agrave ; B -35 -3 685 911 ;
+C -1 ; WX 556 ; N odieresis ; B 48 -17 538 688 ;
+C -1 ; WX 556 ; N oacute ; B 48 -17 504 719 ;
+C -1 ; WX 400 ; N degree ; B 50 383 350 683 ;
+C -1 ; WX 333 ; N igrave ; B 26 -17 322 719 ;
+C -1 ; WX 556 ; N mu ; B -15 -232 521 469 ;
+C -1 ; WX 833 ; N Oacute ; B 76 -17 794 911 ;
+C -1 ; WX 556 ; N eth ; B 48 -17 546 726 ;
+C -1 ; WX 722 ; N Adieresis ; B -35 -3 685 880 ;
+C -1 ; WX 611 ; N Yacute ; B 54 -3 675 911 ;
+C -1 ; WX 606 ; N brokenbar ; B 259 0 347 720 ;
+C -1 ; WX 750 ; N onehalf ; B 14 -2 736 683 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 108
+
+KPX A y -55
+KPX A w -37
+KPX A v -55
+KPX A space -55
+KPX A quoteright -55
+KPX A Y -74
+KPX A W -74
+KPX A V -74
+KPX A T -55
+
+KPX F space -18
+KPX F period -111
+KPX F comma -111
+KPX F A -74
+
+KPX L y -37
+KPX L space -18
+KPX L quoteright -55
+KPX L Y -74
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P space -55
+KPX P period -129
+KPX P comma -129
+KPX P A -92
+
+KPX R y -20
+KPX R Y -37
+KPX R W -55
+KPX R V -55
+KPX R T -37
+
+KPX T y -80
+KPX T w -50
+KPX T u -92
+KPX T semicolon -55
+KPX T s -92
+KPX T r -92
+KPX T period -55
+KPX T o -111
+KPX T i -74
+KPX T hyphen -92
+KPX T e -111
+KPX T comma -55
+KPX T colon -55
+KPX T c -92
+KPX T a -111
+KPX T O -18
+KPX T A -55
+
+KPX V y -50
+KPX V u -50
+KPX V semicolon -37
+KPX V r -74
+KPX V period -111
+KPX V o -74
+KPX V i -50
+KPX V hyphen -37
+KPX V e -74
+KPX V comma -111
+KPX V colon -37
+KPX V a -92
+KPX V A -74
+
+KPX W y -30
+KPX W u -30
+KPX W semicolon -18
+KPX W r -30
+KPX W period -55
+KPX W o -55
+KPX W i -30
+KPX W e -55
+KPX W comma -55
+KPX W colon -28
+KPX W a -74
+KPX W A -74
+
+KPX Y v -30
+KPX Y u -50
+KPX Y semicolon -55
+KPX Y q -92
+KPX Y period -55
+KPX Y p -74
+KPX Y o -111
+KPX Y i -54
+KPX Y hyphen -55
+KPX Y e -92
+KPX Y comma -55
+KPX Y colon -55
+KPX Y a -111
+KPX Y A -55
+
+KPX f quoteright 37
+KPX f f -37
+
+KPX one one -55
+
+KPX quoteleft quoteleft -55
+
+KPX quoteright t -18
+KPX quoteright space -37
+KPX quoteright s -37
+KPX quoteright quoteright -55
+
+KPX r quoteright 55
+KPX r q -18
+KPX r period -55
+KPX r o -18
+KPX r h -18
+KPX r g -18
+KPX r e -18
+KPX r comma -55
+KPX r c -18
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -55
+KPX w comma -55
+
+KPX y period -37
+KPX y comma -37
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 212 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 212 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 212 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 212 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 83 212 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 212 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 176 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 139 212 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 139 212 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 139 212 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 139 212 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 28 212 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 28 212 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 28 212 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 28 212 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 223 212 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 250 212 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 250 212 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 250 212 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 250 212 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 250 212 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 212 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 223 212 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 223 212 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 223 212 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 211 212 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 151 212 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 139 212 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 167 212 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 112 20 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 112 20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 112 20 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 112 20 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 0 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 112 12 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 20 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 20 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 20 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute 0 20 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -12 20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis 0 20 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave 0 20 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 112 12 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 112 20 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 100 20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 112 20 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 112 20 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 112 12 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 44 8 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 112 20 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 100 20 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 20 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 112 20 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 112 20 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 20 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 72 8 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Palatino-Italic.afm b/tlt3.0/library/afm/Palatino-Italic.afm
new file mode 100644
index 0000000..46c2eb5
--- /dev/null
+++ b/tlt3.0/library/afm/Palatino-Italic.afm
@@ -0,0 +1,440 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jul 2 22:37:33 1990
+Comment UniqueID 31796
+Comment VMusage 37415 48307
+FontName Palatino-Italic
+FullName Palatino Italic
+FamilyName Palatino
+Weight Medium
+ItalicAngle -10
+IsFixedPitch false
+FontBBox -170 -276 1010 918
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.005
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Palatino is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 692
+XHeight 482
+Ascender 733
+Descender -276
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 76 -8 292 733 ;
+C 34 ; WX 500 ; N quotedbl ; B 140 508 455 733 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 495 692 ;
+C 36 ; WX 500 ; N dollar ; B 15 -113 452 733 ;
+C 37 ; WX 889 ; N percent ; B 74 -7 809 710 ;
+C 38 ; WX 778 ; N ampersand ; B 47 -18 766 692 ;
+C 39 ; WX 278 ; N quoteright ; B 78 488 258 733 ;
+C 40 ; WX 333 ; N parenleft ; B 54 -106 331 733 ;
+C 41 ; WX 333 ; N parenright ; B 2 -106 279 733 ;
+C 42 ; WX 389 ; N asterisk ; B 76 368 400 706 ;
+C 43 ; WX 606 ; N plus ; B 51 0 555 504 ;
+C 44 ; WX 250 ; N comma ; B 8 -143 203 123 ;
+C 45 ; WX 333 ; N hyphen ; B 19 223 304 281 ;
+C 46 ; WX 250 ; N period ; B 53 -5 158 112 ;
+C 47 ; WX 296 ; N slash ; B -40 -119 392 733 ;
+C 48 ; WX 500 ; N zero ; B 36 -11 480 699 ;
+C 49 ; WX 500 ; N one ; B 54 -3 398 699 ;
+C 50 ; WX 500 ; N two ; B 12 -3 437 699 ;
+C 51 ; WX 500 ; N three ; B 22 -11 447 699 ;
+C 52 ; WX 500 ; N four ; B 15 -3 478 699 ;
+C 53 ; WX 500 ; N five ; B 14 -11 491 693 ;
+C 54 ; WX 500 ; N six ; B 49 -11 469 699 ;
+C 55 ; WX 500 ; N seven ; B 53 -3 502 692 ;
+C 56 ; WX 500 ; N eight ; B 36 -11 469 699 ;
+C 57 ; WX 500 ; N nine ; B 32 -11 468 699 ;
+C 58 ; WX 250 ; N colon ; B 44 -5 207 458 ;
+C 59 ; WX 250 ; N semicolon ; B -9 -146 219 456 ;
+C 60 ; WX 606 ; N less ; B 53 -6 554 516 ;
+C 61 ; WX 606 ; N equal ; B 51 126 555 378 ;
+C 62 ; WX 606 ; N greater ; B 53 -6 554 516 ;
+C 63 ; WX 500 ; N question ; B 114 -8 427 706 ;
+C 64 ; WX 747 ; N at ; B 27 -18 718 706 ;
+C 65 ; WX 722 ; N A ; B -19 -3 677 705 ;
+C 66 ; WX 611 ; N B ; B 26 -6 559 692 ;
+C 67 ; WX 667 ; N C ; B 45 -18 651 706 ;
+C 68 ; WX 778 ; N D ; B 28 -3 741 692 ;
+C 69 ; WX 611 ; N E ; B 30 -3 570 692 ;
+C 70 ; WX 556 ; N F ; B 0 -3 548 692 ;
+C 71 ; WX 722 ; N G ; B 50 -18 694 706 ;
+C 72 ; WX 778 ; N H ; B -3 -3 800 692 ;
+C 73 ; WX 333 ; N I ; B 7 -3 354 692 ;
+C 74 ; WX 333 ; N J ; B -35 -206 358 692 ;
+C 75 ; WX 667 ; N K ; B 13 -3 683 692 ;
+C 76 ; WX 556 ; N L ; B 16 -3 523 692 ;
+C 77 ; WX 944 ; N M ; B -19 -18 940 692 ;
+C 78 ; WX 778 ; N N ; B 2 -11 804 692 ;
+C 79 ; WX 778 ; N O ; B 53 -18 748 706 ;
+C 80 ; WX 611 ; N P ; B 9 -3 594 692 ;
+C 81 ; WX 778 ; N Q ; B 53 -201 748 706 ;
+C 82 ; WX 667 ; N R ; B 9 -3 639 692 ;
+C 83 ; WX 556 ; N S ; B 42 -18 506 706 ;
+C 84 ; WX 611 ; N T ; B 53 -3 635 692 ;
+C 85 ; WX 778 ; N U ; B 88 -18 798 692 ;
+C 86 ; WX 722 ; N V ; B 75 -8 754 692 ;
+C 87 ; WX 944 ; N W ; B 71 -8 980 700 ;
+C 88 ; WX 722 ; N X ; B 20 -3 734 692 ;
+C 89 ; WX 667 ; N Y ; B 52 -3 675 705 ;
+C 90 ; WX 667 ; N Z ; B 20 -3 637 692 ;
+C 91 ; WX 333 ; N bracketleft ; B 18 -100 326 733 ;
+C 92 ; WX 606 ; N backslash ; B 81 0 513 733 ;
+C 93 ; WX 333 ; N bracketright ; B 7 -100 315 733 ;
+C 94 ; WX 606 ; N asciicircum ; B 51 283 554 689 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 78 488 258 733 ;
+C 97 ; WX 444 ; N a ; B 4 -11 406 482 ;
+C 98 ; WX 463 ; N b ; B 37 -11 433 733 ;
+C 99 ; WX 407 ; N c ; B 25 -11 389 482 ;
+C 100 ; WX 500 ; N d ; B 17 -11 483 733 ;
+C 101 ; WX 389 ; N e ; B 15 -11 374 482 ;
+C 102 ; WX 278 ; N f ; B -162 -276 413 733 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B -37 -276 498 482 ;
+C 104 ; WX 500 ; N h ; B 10 -9 471 733 ;
+C 105 ; WX 278 ; N i ; B 34 -9 264 712 ;
+C 106 ; WX 278 ; N j ; B -70 -276 265 712 ;
+C 107 ; WX 444 ; N k ; B 8 -9 449 733 ;
+C 108 ; WX 278 ; N l ; B 36 -9 251 733 ;
+C 109 ; WX 778 ; N m ; B 24 -9 740 482 ;
+C 110 ; WX 556 ; N n ; B 24 -9 514 482 ;
+C 111 ; WX 444 ; N o ; B 17 -11 411 482 ;
+C 112 ; WX 500 ; N p ; B -7 -276 465 482 ;
+C 113 ; WX 463 ; N q ; B 24 -276 432 482 ;
+C 114 ; WX 389 ; N r ; B 26 -9 384 482 ;
+C 115 ; WX 389 ; N s ; B 9 -11 345 482 ;
+C 116 ; WX 333 ; N t ; B 41 -9 310 646 ;
+C 117 ; WX 556 ; N u ; B 32 -11 512 482 ;
+C 118 ; WX 500 ; N v ; B 21 -11 477 482 ;
+C 119 ; WX 722 ; N w ; B 21 -11 699 482 ;
+C 120 ; WX 500 ; N x ; B 9 -11 484 482 ;
+C 121 ; WX 500 ; N y ; B -8 -276 490 482 ;
+C 122 ; WX 444 ; N z ; B -1 -11 416 482 ;
+C 123 ; WX 333 ; N braceleft ; B 15 -100 319 733 ;
+C 124 ; WX 606 ; N bar ; B 275 0 331 733 ;
+C 125 ; WX 333 ; N braceright ; B 14 -100 318 733 ;
+C 126 ; WX 606 ; N asciitilde ; B 51 168 555 339 ;
+C 161 ; WX 333 ; N exclamdown ; B 15 -276 233 467 ;
+C 162 ; WX 500 ; N cent ; B 56 -96 418 551 ;
+C 163 ; WX 500 ; N sterling ; B 2 -18 479 708 ;
+C 164 ; WX 167 ; N fraction ; B -170 0 337 699 ;
+C 165 ; WX 500 ; N yen ; B 35 -3 512 699 ;
+C 166 ; WX 500 ; N florin ; B 5 -276 470 708 ;
+C 167 ; WX 500 ; N section ; B 14 -220 463 706 ;
+C 168 ; WX 500 ; N currency ; B 14 115 486 577 ;
+C 169 ; WX 333 ; N quotesingle ; B 140 508 288 733 ;
+C 170 ; WX 500 ; N quotedblleft ; B 98 488 475 733 ;
+C 171 ; WX 500 ; N guillemotleft ; B 57 70 437 440 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 57 70 270 440 ;
+C 173 ; WX 333 ; N guilsinglright ; B 63 70 276 440 ;
+C 174 ; WX 528 ; N fi ; B -162 -276 502 733 ;
+C 175 ; WX 545 ; N fl ; B -162 -276 520 733 ;
+C 177 ; WX 500 ; N endash ; B -10 228 510 278 ;
+C 178 ; WX 500 ; N dagger ; B 48 0 469 692 ;
+C 179 ; WX 500 ; N daggerdbl ; B 10 -162 494 692 ;
+C 180 ; WX 250 ; N periodcentered ; B 53 195 158 312 ;
+C 182 ; WX 500 ; N paragraph ; B 33 -224 611 692 ;
+C 183 ; WX 500 ; N bullet ; B 86 182 430 526 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 27 -122 211 120 ;
+C 185 ; WX 500 ; N quotedblbase ; B 43 -122 424 120 ;
+C 186 ; WX 500 ; N quotedblright ; B 98 488 475 733 ;
+C 187 ; WX 500 ; N guillemotright ; B 63 70 443 440 ;
+C 188 ; WX 1000 ; N ellipsis ; B 102 -5 873 112 ;
+C 189 ; WX 1000 ; N perthousand ; B 72 -6 929 717 ;
+C 191 ; WX 500 ; N questiondown ; B 57 -246 370 467 ;
+C 193 ; WX 333 ; N grave ; B 86 518 310 687 ;
+C 194 ; WX 333 ; N acute ; B 122 518 346 687 ;
+C 195 ; WX 333 ; N circumflex ; B 56 510 350 679 ;
+C 196 ; WX 333 ; N tilde ; B 63 535 390 638 ;
+C 197 ; WX 333 ; N macron ; B 74 538 386 589 ;
+C 198 ; WX 333 ; N breve ; B 92 518 393 677 ;
+C 199 ; WX 333 ; N dotaccent ; B 175 537 283 645 ;
+C 200 ; WX 333 ; N dieresis ; B 78 537 378 637 ;
+C 202 ; WX 333 ; N ring ; B 159 508 359 708 ;
+C 203 ; WX 333 ; N cedilla ; B -9 -216 202 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 46 518 385 730 ;
+C 206 ; WX 333 ; N ogonek ; B 38 -207 196 -18 ;
+C 207 ; WX 333 ; N caron ; B 104 510 409 679 ;
+C 208 ; WX 1000 ; N emdash ; B -10 228 1010 278 ;
+C 225 ; WX 941 ; N AE ; B -4 -3 902 692 ;
+C 227 ; WX 333 ; N ordfeminine ; B 60 404 321 699 ;
+C 232 ; WX 556 ; N Lslash ; B -16 -3 523 692 ;
+C 233 ; WX 778 ; N Oslash ; B 32 -39 762 721 ;
+C 234 ; WX 1028 ; N OE ; B 56 -18 989 706 ;
+C 235 ; WX 333 ; N ordmasculine ; B 66 404 322 699 ;
+C 241 ; WX 638 ; N ae ; B 1 -11 623 482 ;
+C 245 ; WX 278 ; N dotlessi ; B 34 -9 241 482 ;
+C 248 ; WX 278 ; N lslash ; B -10 -9 302 733 ;
+C 249 ; WX 444 ; N oslash ; B -18 -24 460 510 ;
+C 250 ; WX 669 ; N oe ; B 17 -11 654 482 ;
+C 251 ; WX 500 ; N germandbls ; B -160 -276 488 733 ;
+C -1 ; WX 667 ; N Zcaron ; B 20 -3 637 907 ;
+C -1 ; WX 407 ; N ccedilla ; B 25 -216 389 482 ;
+C -1 ; WX 500 ; N ydieresis ; B -8 -276 490 657 ;
+C -1 ; WX 444 ; N atilde ; B 4 -11 446 650 ;
+C -1 ; WX 278 ; N icircumflex ; B 29 -9 323 699 ;
+C -1 ; WX 300 ; N threesuperior ; B 28 273 304 699 ;
+C -1 ; WX 389 ; N ecircumflex ; B 15 -11 398 699 ;
+C -1 ; WX 500 ; N thorn ; B -39 -276 433 733 ;
+C -1 ; WX 389 ; N egrave ; B 15 -11 374 707 ;
+C -1 ; WX 300 ; N twosuperior ; B 13 278 290 699 ;
+C -1 ; WX 389 ; N eacute ; B 15 -11 394 707 ;
+C -1 ; WX 444 ; N otilde ; B 17 -11 446 650 ;
+C -1 ; WX 722 ; N Aacute ; B -19 -3 677 897 ;
+C -1 ; WX 444 ; N ocircumflex ; B 17 -11 411 699 ;
+C -1 ; WX 500 ; N yacute ; B -8 -276 490 707 ;
+C -1 ; WX 556 ; N udieresis ; B 32 -11 512 657 ;
+C -1 ; WX 750 ; N threequarters ; B 35 -2 715 699 ;
+C -1 ; WX 444 ; N acircumflex ; B 4 -11 406 699 ;
+C -1 ; WX 778 ; N Eth ; B 19 -3 741 692 ;
+C -1 ; WX 389 ; N edieresis ; B 15 -11 406 657 ;
+C -1 ; WX 556 ; N ugrave ; B 32 -11 512 707 ;
+C -1 ; WX 1000 ; N trademark ; B 52 285 951 689 ;
+C -1 ; WX 444 ; N ograve ; B 17 -11 411 707 ;
+C -1 ; WX 389 ; N scaron ; B 9 -11 419 687 ;
+C -1 ; WX 333 ; N Idieresis ; B 7 -3 418 847 ;
+C -1 ; WX 556 ; N uacute ; B 32 -11 512 707 ;
+C -1 ; WX 444 ; N agrave ; B 4 -11 406 707 ;
+C -1 ; WX 556 ; N ntilde ; B 24 -9 514 650 ;
+C -1 ; WX 444 ; N aring ; B 4 -11 406 728 ;
+C -1 ; WX 444 ; N zcaron ; B -1 -11 447 687 ;
+C -1 ; WX 333 ; N Icircumflex ; B 7 -3 390 889 ;
+C -1 ; WX 778 ; N Ntilde ; B 2 -11 804 866 ;
+C -1 ; WX 556 ; N ucircumflex ; B 32 -11 512 699 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 30 -3 570 889 ;
+C -1 ; WX 333 ; N Iacute ; B 7 -3 406 897 ;
+C -1 ; WX 667 ; N Ccedilla ; B 45 -216 651 706 ;
+C -1 ; WX 778 ; N Odieresis ; B 53 -18 748 847 ;
+C -1 ; WX 556 ; N Scaron ; B 42 -18 539 907 ;
+C -1 ; WX 611 ; N Edieresis ; B 30 -3 570 847 ;
+C -1 ; WX 333 ; N Igrave ; B 7 -3 354 897 ;
+C -1 ; WX 444 ; N adieresis ; B 4 -11 434 657 ;
+C -1 ; WX 778 ; N Ograve ; B 53 -18 748 897 ;
+C -1 ; WX 611 ; N Egrave ; B 30 -3 570 897 ;
+C -1 ; WX 667 ; N Ydieresis ; B 52 -3 675 847 ;
+C -1 ; WX 747 ; N registered ; B 11 -18 736 706 ;
+C -1 ; WX 778 ; N Otilde ; B 53 -18 748 866 ;
+C -1 ; WX 750 ; N onequarter ; B 31 -2 715 699 ;
+C -1 ; WX 778 ; N Ugrave ; B 88 -18 798 897 ;
+C -1 ; WX 778 ; N Ucircumflex ; B 88 -18 798 889 ;
+C -1 ; WX 611 ; N Thorn ; B 9 -3 570 692 ;
+C -1 ; WX 606 ; N divide ; B 51 0 555 504 ;
+C -1 ; WX 722 ; N Atilde ; B -19 -3 677 866 ;
+C -1 ; WX 778 ; N Uacute ; B 88 -18 798 897 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 53 -18 748 889 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 118 555 378 ;
+C -1 ; WX 722 ; N Aring ; B -19 -3 677 918 ;
+C -1 ; WX 278 ; N idieresis ; B 34 -9 351 657 ;
+C -1 ; WX 278 ; N iacute ; B 34 -9 331 707 ;
+C -1 ; WX 444 ; N aacute ; B 4 -11 414 707 ;
+C -1 ; WX 606 ; N plusminus ; B 51 0 555 504 ;
+C -1 ; WX 606 ; N multiply ; B 83 36 523 474 ;
+C -1 ; WX 778 ; N Udieresis ; B 88 -18 798 847 ;
+C -1 ; WX 606 ; N minus ; B 51 224 555 280 ;
+C -1 ; WX 300 ; N onesuperior ; B 61 278 285 699 ;
+C -1 ; WX 611 ; N Eacute ; B 30 -3 570 897 ;
+C -1 ; WX 722 ; N Acircumflex ; B -19 -3 677 889 ;
+C -1 ; WX 747 ; N copyright ; B 11 -18 736 706 ;
+C -1 ; WX 722 ; N Agrave ; B -19 -3 677 897 ;
+C -1 ; WX 444 ; N odieresis ; B 17 -11 434 657 ;
+C -1 ; WX 444 ; N oacute ; B 17 -11 414 707 ;
+C -1 ; WX 400 ; N degree ; B 90 389 390 689 ;
+C -1 ; WX 278 ; N igrave ; B 34 -9 271 707 ;
+C -1 ; WX 556 ; N mu ; B 15 -226 512 482 ;
+C -1 ; WX 778 ; N Oacute ; B 53 -18 748 897 ;
+C -1 ; WX 444 ; N eth ; B 17 -11 478 733 ;
+C -1 ; WX 722 ; N Adieresis ; B -19 -3 677 847 ;
+C -1 ; WX 667 ; N Yacute ; B 52 -3 675 897 ;
+C -1 ; WX 606 ; N brokenbar ; B 275 0 331 733 ;
+C -1 ; WX 750 ; N onehalf ; B 31 -2 721 699 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 106
+
+KPX A y -55
+KPX A w -37
+KPX A v -37
+KPX A space -37
+KPX A quoteright -55
+KPX A Y -55
+KPX A W -55
+KPX A V -74
+KPX A T -55
+
+KPX F period -111
+KPX F comma -111
+KPX F A -111
+
+KPX L y -37
+KPX L space -18
+KPX L quoteright -37
+KPX L Y -74
+KPX L W -74
+KPX L V -74
+KPX L T -74
+
+KPX P period -129
+KPX P comma -129
+KPX P A -129
+
+KPX R y -37
+KPX R Y -55
+KPX R W -55
+KPX R V -74
+KPX R T -55
+
+KPX T y -92
+KPX T w -92
+KPX T u -111
+KPX T semicolon -74
+KPX T s -111
+KPX T r -111
+KPX T period -74
+KPX T o -111
+KPX T i -55
+KPX T hyphen -55
+KPX T e -111
+KPX T comma -74
+KPX T colon -74
+KPX T c -111
+KPX T a -111
+KPX T O -18
+KPX T A -92
+
+KPX V y -74
+KPX V u -74
+KPX V semicolon -37
+KPX V r -92
+KPX V period -129
+KPX V o -74
+KPX V i -74
+KPX V hyphen -55
+KPX V e -92
+KPX V comma -129
+KPX V colon -37
+KPX V a -74
+KPX V A -210
+
+KPX W y -20
+KPX W u -20
+KPX W semicolon -18
+KPX W r -20
+KPX W period -55
+KPX W o -20
+KPX W i -20
+KPX W hyphen -18
+KPX W e -20
+KPX W comma -55
+KPX W colon -18
+KPX W a -20
+KPX W A -92
+
+KPX Y v -74
+KPX Y u -92
+KPX Y semicolon -74
+KPX Y q -92
+KPX Y period -92
+KPX Y p -74
+KPX Y o -111
+KPX Y i -55
+KPX Y hyphen -74
+KPX Y e -111
+KPX Y comma -92
+KPX Y colon -74
+KPX Y a -92
+KPX Y A -92
+
+KPX f quoteright 55
+
+KPX one one -55
+
+KPX quoteleft quoteleft -74
+
+KPX quoteright t -37
+KPX quoteright space -55
+KPX quoteright s -55
+KPX quoteright quoteright -74
+
+KPX r quoteright 37
+KPX r q -18
+KPX r period -74
+KPX r o -18
+KPX r h -18
+KPX r g -18
+KPX r e -18
+KPX r comma -74
+KPX r c -18
+
+KPX v period -55
+KPX v comma -55
+
+KPX w period -55
+KPX w comma -55
+
+KPX y period -37
+KPX y comma -37
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 271 210 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 261 210 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 255 210 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 235 210 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 235 210 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 255 228 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 207 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 199 210 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 179 210 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 179 210 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 167 210 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 60 210 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 40 210 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 40 210 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 28 210 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 263 228 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 283 210 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 263 210 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 255 210 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 251 210 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 263 228 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 130 228 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 277 210 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 255 210 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 235 210 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 235 210 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 227 210 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 187 210 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 179 228 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 68 20 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 56 20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 56 20 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 44 20 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 36 20 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 56 12 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 37 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 48 20 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 48 20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 28 20 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 16 20 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -15 20 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 20 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -39 20 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 112 12 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 68 20 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 56 20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 56 20 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 36 20 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 56 12 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 10 8 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 124 20 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 20 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 112 20 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 100 20 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 96 20 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 20 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 38 8 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Palatino-Roman.afm b/tlt3.0/library/afm/Palatino-Roman.afm
new file mode 100644
index 0000000..c7b7aff
--- /dev/null
+++ b/tlt3.0/library/afm/Palatino-Roman.afm
@@ -0,0 +1,446 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Mon Jul 2 22:14:17 1990
+Comment UniqueID 31790
+Comment VMusage 36445 47337
+FontName Palatino-Roman
+FullName Palatino Roman
+FamilyName Palatino
+Weight Roman
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -166 -283 1021 927
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.005
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Palatino is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 692
+XHeight 469
+Ascender 726
+Descender -281
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 278 ; N exclam ; B 81 -5 197 694 ;
+C 34 ; WX 371 ; N quotedbl ; B 52 469 319 709 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 495 684 ;
+C 36 ; WX 500 ; N dollar ; B 30 -116 471 731 ;
+C 37 ; WX 840 ; N percent ; B 39 -20 802 709 ;
+C 38 ; WX 778 ; N ampersand ; B 43 -20 753 689 ;
+C 39 ; WX 278 ; N quoteright ; B 45 446 233 709 ;
+C 40 ; WX 333 ; N parenleft ; B 60 -215 301 726 ;
+C 41 ; WX 333 ; N parenright ; B 32 -215 273 726 ;
+C 42 ; WX 389 ; N asterisk ; B 32 342 359 689 ;
+C 43 ; WX 606 ; N plus ; B 51 7 555 512 ;
+C 44 ; WX 250 ; N comma ; B 16 -155 218 123 ;
+C 45 ; WX 333 ; N hyphen ; B 17 215 312 287 ;
+C 46 ; WX 250 ; N period ; B 67 -5 183 111 ;
+C 47 ; WX 606 ; N slash ; B 87 -119 519 726 ;
+C 48 ; WX 500 ; N zero ; B 29 -20 465 689 ;
+C 49 ; WX 500 ; N one ; B 60 -3 418 694 ;
+C 50 ; WX 500 ; N two ; B 16 -3 468 689 ;
+C 51 ; WX 500 ; N three ; B 15 -20 462 689 ;
+C 52 ; WX 500 ; N four ; B 2 -3 472 694 ;
+C 53 ; WX 500 ; N five ; B 13 -20 459 689 ;
+C 54 ; WX 500 ; N six ; B 32 -20 468 689 ;
+C 55 ; WX 500 ; N seven ; B 44 -3 497 689 ;
+C 56 ; WX 500 ; N eight ; B 30 -20 464 689 ;
+C 57 ; WX 500 ; N nine ; B 20 -20 457 689 ;
+C 58 ; WX 250 ; N colon ; B 66 -5 182 456 ;
+C 59 ; WX 250 ; N semicolon ; B 16 -153 218 456 ;
+C 60 ; WX 606 ; N less ; B 57 0 558 522 ;
+C 61 ; WX 606 ; N equal ; B 51 136 555 386 ;
+C 62 ; WX 606 ; N greater ; B 48 0 549 522 ;
+C 63 ; WX 444 ; N question ; B 43 -5 395 694 ;
+C 64 ; WX 747 ; N at ; B 24 -20 724 694 ;
+C 65 ; WX 778 ; N A ; B 15 -3 756 700 ;
+C 66 ; WX 611 ; N B ; B 26 -3 576 692 ;
+C 67 ; WX 709 ; N C ; B 22 -20 670 709 ;
+C 68 ; WX 774 ; N D ; B 22 -3 751 692 ;
+C 69 ; WX 611 ; N E ; B 22 -3 572 692 ;
+C 70 ; WX 556 ; N F ; B 22 -3 536 692 ;
+C 71 ; WX 763 ; N G ; B 22 -20 728 709 ;
+C 72 ; WX 832 ; N H ; B 22 -3 810 692 ;
+C 73 ; WX 337 ; N I ; B 22 -3 315 692 ;
+C 74 ; WX 333 ; N J ; B -15 -194 311 692 ;
+C 75 ; WX 726 ; N K ; B 22 -3 719 692 ;
+C 76 ; WX 611 ; N L ; B 22 -3 586 692 ;
+C 77 ; WX 946 ; N M ; B 16 -13 926 692 ;
+C 78 ; WX 831 ; N N ; B 17 -20 813 692 ;
+C 79 ; WX 786 ; N O ; B 22 -20 764 709 ;
+C 80 ; WX 604 ; N P ; B 22 -3 580 692 ;
+C 81 ; WX 786 ; N Q ; B 22 -176 764 709 ;
+C 82 ; WX 668 ; N R ; B 22 -3 669 692 ;
+C 83 ; WX 525 ; N S ; B 24 -20 503 709 ;
+C 84 ; WX 613 ; N T ; B 18 -3 595 692 ;
+C 85 ; WX 778 ; N U ; B 12 -20 759 692 ;
+C 86 ; WX 722 ; N V ; B 8 -9 706 692 ;
+C 87 ; WX 1000 ; N W ; B 8 -9 984 700 ;
+C 88 ; WX 667 ; N X ; B 14 -3 648 700 ;
+C 89 ; WX 667 ; N Y ; B 9 -3 654 704 ;
+C 90 ; WX 667 ; N Z ; B 15 -3 638 692 ;
+C 91 ; WX 333 ; N bracketleft ; B 79 -184 288 726 ;
+C 92 ; WX 606 ; N backslash ; B 81 0 512 726 ;
+C 93 ; WX 333 ; N bracketright ; B 45 -184 254 726 ;
+C 94 ; WX 606 ; N asciicircum ; B 51 283 554 689 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 278 ; N quoteleft ; B 45 446 233 709 ;
+C 97 ; WX 500 ; N a ; B 32 -12 471 469 ;
+C 98 ; WX 553 ; N b ; B -15 -12 508 726 ;
+C 99 ; WX 444 ; N c ; B 26 -20 413 469 ;
+C 100 ; WX 611 ; N d ; B 35 -12 579 726 ;
+C 101 ; WX 479 ; N e ; B 26 -20 448 469 ;
+C 102 ; WX 333 ; N f ; B 23 -3 341 728 ; L i fi ; L l fl ;
+C 103 ; WX 556 ; N g ; B 32 -283 544 469 ;
+C 104 ; WX 582 ; N h ; B 6 -3 572 726 ;
+C 105 ; WX 291 ; N i ; B 21 -3 271 687 ;
+C 106 ; WX 234 ; N j ; B -40 -283 167 688 ;
+C 107 ; WX 556 ; N k ; B 21 -12 549 726 ;
+C 108 ; WX 291 ; N l ; B 21 -3 271 726 ;
+C 109 ; WX 883 ; N m ; B 16 -3 869 469 ;
+C 110 ; WX 582 ; N n ; B 6 -3 572 469 ;
+C 111 ; WX 546 ; N o ; B 32 -20 514 469 ;
+C 112 ; WX 601 ; N p ; B 8 -281 554 469 ;
+C 113 ; WX 560 ; N q ; B 35 -281 560 469 ;
+C 114 ; WX 395 ; N r ; B 21 -3 374 469 ;
+C 115 ; WX 424 ; N s ; B 30 -20 391 469 ;
+C 116 ; WX 326 ; N t ; B 22 -12 319 621 ;
+C 117 ; WX 603 ; N u ; B 18 -12 581 469 ;
+C 118 ; WX 565 ; N v ; B 6 -7 539 459 ;
+C 119 ; WX 834 ; N w ; B 6 -7 808 469 ;
+C 120 ; WX 516 ; N x ; B 20 -3 496 469 ;
+C 121 ; WX 556 ; N y ; B 12 -283 544 459 ;
+C 122 ; WX 500 ; N z ; B 16 -3 466 462 ;
+C 123 ; WX 333 ; N braceleft ; B 58 -175 289 726 ;
+C 124 ; WX 606 ; N bar ; B 275 0 331 726 ;
+C 125 ; WX 333 ; N braceright ; B 44 -175 275 726 ;
+C 126 ; WX 606 ; N asciitilde ; B 51 176 555 347 ;
+C 161 ; WX 278 ; N exclamdown ; B 81 -225 197 469 ;
+C 162 ; WX 500 ; N cent ; B 61 -101 448 562 ;
+C 163 ; WX 500 ; N sterling ; B 12 -13 478 694 ;
+C 164 ; WX 167 ; N fraction ; B -166 0 337 689 ;
+C 165 ; WX 500 ; N yen ; B 5 -3 496 701 ;
+C 166 ; WX 500 ; N florin ; B 0 -262 473 706 ;
+C 167 ; WX 500 ; N section ; B 26 -219 465 709 ;
+C 168 ; WX 500 ; N currency ; B 30 96 470 531 ;
+C 169 ; WX 208 ; N quotesingle ; B 61 469 147 709 ;
+C 170 ; WX 500 ; N quotedblleft ; B 51 446 449 709 ;
+C 171 ; WX 500 ; N guillemotleft ; B 50 71 450 428 ;
+C 172 ; WX 331 ; N guilsinglleft ; B 66 71 265 428 ;
+C 173 ; WX 331 ; N guilsinglright ; B 66 71 265 428 ;
+C 174 ; WX 605 ; N fi ; B 23 -3 587 728 ;
+C 175 ; WX 608 ; N fl ; B 23 -3 590 728 ;
+C 177 ; WX 500 ; N endash ; B 0 219 500 277 ;
+C 178 ; WX 500 ; N dagger ; B 34 -5 466 694 ;
+C 179 ; WX 500 ; N daggerdbl ; B 34 -249 466 694 ;
+C 180 ; WX 250 ; N periodcentered ; B 67 203 183 319 ;
+C 182 ; WX 628 ; N paragraph ; B 39 -150 589 694 ;
+C 183 ; WX 606 ; N bullet ; B 131 172 475 516 ;
+C 184 ; WX 278 ; N quotesinglbase ; B 22 -153 210 110 ;
+C 185 ; WX 500 ; N quotedblbase ; B 51 -153 449 110 ;
+C 186 ; WX 500 ; N quotedblright ; B 51 446 449 709 ;
+C 187 ; WX 500 ; N guillemotright ; B 50 71 450 428 ;
+C 188 ; WX 1000 ; N ellipsis ; B 109 -5 891 111 ;
+C 189 ; WX 1144 ; N perthousand ; B 123 -20 1021 709 ;
+C 191 ; WX 444 ; N questiondown ; B 43 -231 395 469 ;
+C 193 ; WX 333 ; N grave ; B 31 506 255 677 ;
+C 194 ; WX 333 ; N acute ; B 78 506 302 677 ;
+C 195 ; WX 333 ; N circumflex ; B 11 510 323 677 ;
+C 196 ; WX 333 ; N tilde ; B 2 535 332 640 ;
+C 197 ; WX 333 ; N macron ; B 11 538 323 591 ;
+C 198 ; WX 333 ; N breve ; B 26 506 308 664 ;
+C 199 ; WX 250 ; N dotaccent ; B 75 537 175 637 ;
+C 200 ; WX 333 ; N dieresis ; B 17 537 316 637 ;
+C 202 ; WX 333 ; N ring ; B 67 496 267 696 ;
+C 203 ; WX 333 ; N cedilla ; B 96 -225 304 -10 ;
+C 205 ; WX 380 ; N hungarumlaut ; B 3 506 377 687 ;
+C 206 ; WX 313 ; N ogonek ; B 68 -165 245 -20 ;
+C 207 ; WX 333 ; N caron ; B 11 510 323 677 ;
+C 208 ; WX 1000 ; N emdash ; B 0 219 1000 277 ;
+C 225 ; WX 944 ; N AE ; B -10 -3 908 692 ;
+C 227 ; WX 333 ; N ordfeminine ; B 24 422 310 709 ;
+C 232 ; WX 611 ; N Lslash ; B 6 -3 586 692 ;
+C 233 ; WX 833 ; N Oslash ; B 30 -20 797 709 ;
+C 234 ; WX 998 ; N OE ; B 22 -20 962 709 ;
+C 235 ; WX 333 ; N ordmasculine ; B 10 416 323 709 ;
+C 241 ; WX 758 ; N ae ; B 30 -20 732 469 ;
+C 245 ; WX 287 ; N dotlessi ; B 21 -3 271 469 ;
+C 248 ; WX 291 ; N lslash ; B -14 -3 306 726 ;
+C 249 ; WX 556 ; N oslash ; B 16 -23 530 474 ;
+C 250 ; WX 827 ; N oe ; B 32 -20 800 469 ;
+C 251 ; WX 556 ; N germandbls ; B 23 -9 519 731 ;
+C -1 ; WX 667 ; N Zcaron ; B 15 -3 638 908 ;
+C -1 ; WX 444 ; N ccedilla ; B 26 -225 413 469 ;
+C -1 ; WX 556 ; N ydieresis ; B 12 -283 544 657 ;
+C -1 ; WX 500 ; N atilde ; B 32 -12 471 652 ;
+C -1 ; WX 287 ; N icircumflex ; B -12 -3 300 697 ;
+C -1 ; WX 300 ; N threesuperior ; B 1 266 299 689 ;
+C -1 ; WX 479 ; N ecircumflex ; B 26 -20 448 697 ;
+C -1 ; WX 601 ; N thorn ; B -2 -281 544 726 ;
+C -1 ; WX 479 ; N egrave ; B 26 -20 448 697 ;
+C -1 ; WX 300 ; N twosuperior ; B 0 273 301 689 ;
+C -1 ; WX 479 ; N eacute ; B 26 -20 448 697 ;
+C -1 ; WX 546 ; N otilde ; B 32 -20 514 652 ;
+C -1 ; WX 778 ; N Aacute ; B 15 -3 756 908 ;
+C -1 ; WX 546 ; N ocircumflex ; B 32 -20 514 697 ;
+C -1 ; WX 556 ; N yacute ; B 12 -283 544 697 ;
+C -1 ; WX 603 ; N udieresis ; B 18 -12 581 657 ;
+C -1 ; WX 750 ; N threequarters ; B 15 -3 735 689 ;
+C -1 ; WX 500 ; N acircumflex ; B 32 -12 471 697 ;
+C -1 ; WX 774 ; N Eth ; B 14 -3 751 692 ;
+C -1 ; WX 479 ; N edieresis ; B 26 -20 448 657 ;
+C -1 ; WX 603 ; N ugrave ; B 18 -12 581 697 ;
+C -1 ; WX 979 ; N trademark ; B 40 285 939 689 ;
+C -1 ; WX 546 ; N ograve ; B 32 -20 514 697 ;
+C -1 ; WX 424 ; N scaron ; B 30 -20 391 685 ;
+C -1 ; WX 337 ; N Idieresis ; B 19 -3 318 868 ;
+C -1 ; WX 603 ; N uacute ; B 18 -12 581 697 ;
+C -1 ; WX 500 ; N agrave ; B 32 -12 471 697 ;
+C -1 ; WX 582 ; N ntilde ; B 6 -3 572 652 ;
+C -1 ; WX 500 ; N aring ; B 32 -12 471 716 ;
+C -1 ; WX 500 ; N zcaron ; B 16 -3 466 685 ;
+C -1 ; WX 337 ; N Icircumflex ; B 13 -3 325 908 ;
+C -1 ; WX 831 ; N Ntilde ; B 17 -20 813 871 ;
+C -1 ; WX 603 ; N ucircumflex ; B 18 -12 581 697 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 22 -3 572 908 ;
+C -1 ; WX 337 ; N Iacute ; B 22 -3 315 908 ;
+C -1 ; WX 709 ; N Ccedilla ; B 22 -225 670 709 ;
+C -1 ; WX 786 ; N Odieresis ; B 22 -20 764 868 ;
+C -1 ; WX 525 ; N Scaron ; B 24 -20 503 908 ;
+C -1 ; WX 611 ; N Edieresis ; B 22 -3 572 868 ;
+C -1 ; WX 337 ; N Igrave ; B 22 -3 315 908 ;
+C -1 ; WX 500 ; N adieresis ; B 32 -12 471 657 ;
+C -1 ; WX 786 ; N Ograve ; B 22 -20 764 908 ;
+C -1 ; WX 611 ; N Egrave ; B 22 -3 572 908 ;
+C -1 ; WX 667 ; N Ydieresis ; B 9 -3 654 868 ;
+C -1 ; WX 747 ; N registered ; B 11 -18 736 706 ;
+C -1 ; WX 786 ; N Otilde ; B 22 -20 764 883 ;
+C -1 ; WX 750 ; N onequarter ; B 30 -3 727 692 ;
+C -1 ; WX 778 ; N Ugrave ; B 12 -20 759 908 ;
+C -1 ; WX 778 ; N Ucircumflex ; B 12 -20 759 908 ;
+C -1 ; WX 604 ; N Thorn ; B 32 -3 574 692 ;
+C -1 ; WX 606 ; N divide ; B 51 10 555 512 ;
+C -1 ; WX 778 ; N Atilde ; B 15 -3 756 871 ;
+C -1 ; WX 778 ; N Uacute ; B 12 -20 759 908 ;
+C -1 ; WX 786 ; N Ocircumflex ; B 22 -20 764 908 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 120 551 386 ;
+C -1 ; WX 778 ; N Aring ; B 15 -3 756 927 ;
+C -1 ; WX 287 ; N idieresis ; B -6 -3 293 657 ;
+C -1 ; WX 287 ; N iacute ; B 21 -3 279 697 ;
+C -1 ; WX 500 ; N aacute ; B 32 -12 471 697 ;
+C -1 ; WX 606 ; N plusminus ; B 51 0 555 512 ;
+C -1 ; WX 606 ; N multiply ; B 83 36 523 474 ;
+C -1 ; WX 778 ; N Udieresis ; B 12 -20 759 868 ;
+C -1 ; WX 606 ; N minus ; B 51 233 555 289 ;
+C -1 ; WX 300 ; N onesuperior ; B 31 273 269 692 ;
+C -1 ; WX 611 ; N Eacute ; B 22 -3 572 908 ;
+C -1 ; WX 778 ; N Acircumflex ; B 15 -3 756 908 ;
+C -1 ; WX 747 ; N copyright ; B 11 -18 736 706 ;
+C -1 ; WX 778 ; N Agrave ; B 15 -3 756 908 ;
+C -1 ; WX 546 ; N odieresis ; B 32 -20 514 657 ;
+C -1 ; WX 546 ; N oacute ; B 32 -20 514 697 ;
+C -1 ; WX 400 ; N degree ; B 50 389 350 689 ;
+C -1 ; WX 287 ; N igrave ; B 8 -3 271 697 ;
+C -1 ; WX 603 ; N mu ; B 18 -236 581 469 ;
+C -1 ; WX 786 ; N Oacute ; B 22 -20 764 908 ;
+C -1 ; WX 546 ; N eth ; B 32 -20 504 728 ;
+C -1 ; WX 778 ; N Adieresis ; B 15 -3 756 868 ;
+C -1 ; WX 667 ; N Yacute ; B 9 -3 654 908 ;
+C -1 ; WX 606 ; N brokenbar ; B 275 0 331 726 ;
+C -1 ; WX 750 ; N onehalf ; B 15 -3 735 692 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 111
+
+KPX A y -74
+KPX A w -74
+KPX A v -92
+KPX A space -55
+KPX A quoteright -74
+KPX A Y -111
+KPX A W -74
+KPX A V -111
+KPX A T -74
+
+KPX F period -92
+KPX F comma -92
+KPX F A -74
+
+KPX L y -55
+KPX L space -37
+KPX L quoteright -74
+KPX L Y -92
+KPX L W -74
+KPX L V -92
+KPX L T -74
+
+KPX P space -18
+KPX P period -129
+KPX P comma -129
+KPX P A -92
+
+KPX R y -37
+KPX R Y -37
+KPX R W -37
+KPX R V -55
+KPX R T -37
+
+KPX T y -90
+KPX T w -90
+KPX T u -90
+KPX T semicolon -55
+KPX T s -90
+KPX T r -90
+KPX T period -74
+KPX T o -92
+KPX T i -55
+KPX T hyphen -55
+KPX T e -92
+KPX T comma -74
+KPX T colon -55
+KPX T c -111
+KPX T a -92
+KPX T O -18
+KPX T A -74
+
+KPX V y -92
+KPX V u -92
+KPX V semicolon -55
+KPX V r -92
+KPX V period -129
+KPX V o -111
+KPX V i -55
+KPX V hyphen -74
+KPX V e -111
+KPX V comma -129
+KPX V colon -55
+KPX V a -92
+KPX V A -111
+
+KPX W y -50
+KPX W u -50
+KPX W semicolon -18
+KPX W r -74
+KPX W period -92
+KPX W o -92
+KPX W i -55
+KPX W hyphen -55
+KPX W e -92
+KPX W comma -92
+KPX W colon -18
+KPX W a -92
+KPX W A -92
+
+KPX Y v -90
+KPX Y u -90
+KPX Y space -18
+KPX Y semicolon -74
+KPX Y q -90
+KPX Y period -111
+KPX Y p -111
+KPX Y o -92
+KPX Y i -55
+KPX Y hyphen -92
+KPX Y e -92
+KPX Y comma -111
+KPX Y colon -74
+KPX Y a -92
+KPX Y A -92
+
+KPX f quoteright 55
+KPX f f -18
+
+KPX one one -55
+
+KPX quoteleft quoteleft -37
+
+KPX quoteright quoteright -37
+
+KPX r u -8
+KPX r quoteright 74
+KPX r q -18
+KPX r period -74
+KPX r o -18
+KPX r hyphen -18
+KPX r h -18
+KPX r g -18
+KPX r e -18
+KPX r d -18
+KPX r comma -74
+KPX r c -18
+
+KPX space Y -18
+KPX space A -37
+
+KPX v period -111
+KPX v comma -111
+
+KPX w period -92
+KPX w comma -92
+
+KPX y period -111
+KPX y comma -111
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 229 231 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 223 231 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 223 231 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 215 231 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 223 231 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 223 231 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 188 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 139 231 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 139 231 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 139 231 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 139 231 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 2 231 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 2 231 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 2 231 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 2 231 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 249 231 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 227 231 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 227 231 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 227 231 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 227 231 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 227 243 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 96 231 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 255 231 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 247 231 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 223 231 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 223 231 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 203 231 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 191 231 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 179 231 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 20 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 72 20 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 72 20 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 60 20 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 72 20 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 72 12 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 97 20 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 85 20 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 73 20 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 73 20 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -23 20 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -23 20 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -23 20 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -23 20 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 113 12 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 107 20 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 107 20 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 107 20 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 95 20 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 107 12 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 46 8 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 159 20 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 135 20 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 135 20 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 111 20 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 144 20 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 112 20 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 84 8 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Symbol.afm b/tlt3.0/library/afm/Symbol.afm
new file mode 100644
index 0000000..6f07472
--- /dev/null
+++ b/tlt3.0/library/afm/Symbol.afm
@@ -0,0 +1,210 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Wed Jan 17 21:48:26 1990
+Comment UniqueID 27004
+Comment VMusage 28489 37622
+FontName Symbol
+FullName Symbol
+FamilyName Symbol
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -180 -293 1090 1010
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All rights reserved.
+EncodingScheme FontSpecific
+StartCharMetrics 189
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 128 -17 240 672 ;
+C 34 ; WX 713 ; N universal ; B 31 0 681 705 ;
+C 35 ; WX 500 ; N numbersign ; B 20 -16 481 673 ;
+C 36 ; WX 549 ; N existential ; B 25 0 478 707 ;
+C 37 ; WX 833 ; N percent ; B 63 -36 771 655 ;
+C 38 ; WX 778 ; N ampersand ; B 41 -18 750 661 ;
+C 39 ; WX 439 ; N suchthat ; B 48 -17 414 500 ;
+C 40 ; WX 333 ; N parenleft ; B 53 -191 300 673 ;
+C 41 ; WX 333 ; N parenright ; B 30 -191 277 673 ;
+C 42 ; WX 500 ; N asteriskmath ; B 65 134 427 551 ;
+C 43 ; WX 549 ; N plus ; B 10 0 539 533 ;
+C 44 ; WX 250 ; N comma ; B 56 -152 194 104 ;
+C 45 ; WX 549 ; N minus ; B 11 233 535 288 ;
+C 46 ; WX 250 ; N period ; B 69 -17 181 95 ;
+C 47 ; WX 278 ; N slash ; B 0 -18 254 646 ;
+C 48 ; WX 500 ; N zero ; B 23 -17 471 685 ;
+C 49 ; WX 500 ; N one ; B 117 0 390 673 ;
+C 50 ; WX 500 ; N two ; B 25 0 475 686 ;
+C 51 ; WX 500 ; N three ; B 39 -17 435 685 ;
+C 52 ; WX 500 ; N four ; B 16 0 469 685 ;
+C 53 ; WX 500 ; N five ; B 29 -17 443 685 ;
+C 54 ; WX 500 ; N six ; B 36 -17 467 685 ;
+C 55 ; WX 500 ; N seven ; B 24 -16 448 673 ;
+C 56 ; WX 500 ; N eight ; B 54 -18 440 685 ;
+C 57 ; WX 500 ; N nine ; B 31 -18 460 685 ;
+C 58 ; WX 278 ; N colon ; B 81 -17 193 460 ;
+C 59 ; WX 278 ; N semicolon ; B 83 -152 221 460 ;
+C 60 ; WX 549 ; N less ; B 26 0 523 522 ;
+C 61 ; WX 549 ; N equal ; B 11 141 537 390 ;
+C 62 ; WX 549 ; N greater ; B 26 0 523 522 ;
+C 63 ; WX 444 ; N question ; B 70 -17 412 686 ;
+C 64 ; WX 549 ; N congruent ; B 11 0 537 475 ;
+C 65 ; WX 722 ; N Alpha ; B 4 0 684 673 ;
+C 66 ; WX 667 ; N Beta ; B 29 0 592 673 ;
+C 67 ; WX 722 ; N Chi ; B -9 0 704 673 ;
+C 68 ; WX 612 ; N Delta ; B 6 0 608 688 ;
+C 69 ; WX 611 ; N Epsilon ; B 32 0 617 673 ;
+C 70 ; WX 763 ; N Phi ; B 26 0 741 673 ;
+C 71 ; WX 603 ; N Gamma ; B 24 0 609 673 ;
+C 72 ; WX 722 ; N Eta ; B 39 0 729 673 ;
+C 73 ; WX 333 ; N Iota ; B 32 0 316 673 ;
+C 74 ; WX 631 ; N theta1 ; B 18 -18 623 689 ;
+C 75 ; WX 722 ; N Kappa ; B 35 0 722 673 ;
+C 76 ; WX 686 ; N Lambda ; B 6 0 680 688 ;
+C 77 ; WX 889 ; N Mu ; B 28 0 887 673 ;
+C 78 ; WX 722 ; N Nu ; B 29 -8 720 673 ;
+C 79 ; WX 722 ; N Omicron ; B 41 -17 715 685 ;
+C 80 ; WX 768 ; N Pi ; B 25 0 745 673 ;
+C 81 ; WX 741 ; N Theta ; B 41 -17 715 685 ;
+C 82 ; WX 556 ; N Rho ; B 28 0 563 673 ;
+C 83 ; WX 592 ; N Sigma ; B 5 0 589 673 ;
+C 84 ; WX 611 ; N Tau ; B 33 0 607 673 ;
+C 85 ; WX 690 ; N Upsilon ; B -8 0 694 673 ;
+C 86 ; WX 439 ; N sigma1 ; B 40 -233 436 500 ;
+C 87 ; WX 768 ; N Omega ; B 34 0 736 688 ;
+C 88 ; WX 645 ; N Xi ; B 40 0 599 673 ;
+C 89 ; WX 795 ; N Psi ; B 15 0 781 684 ;
+C 90 ; WX 611 ; N Zeta ; B 44 0 636 673 ;
+C 91 ; WX 333 ; N bracketleft ; B 86 -155 299 674 ;
+C 92 ; WX 863 ; N therefore ; B 163 0 701 478 ;
+C 93 ; WX 333 ; N bracketright ; B 33 -155 246 674 ;
+C 94 ; WX 658 ; N perpendicular ; B 15 0 652 674 ;
+C 95 ; WX 500 ; N underscore ; B -2 -252 502 -206 ;
+C 96 ; WX 500 ; N radicalex ; B 480 881 1090 917 ;
+C 97 ; WX 631 ; N alpha ; B 41 -18 622 500 ;
+C 98 ; WX 549 ; N beta ; B 61 -223 515 741 ;
+C 99 ; WX 549 ; N chi ; B 12 -231 522 499 ;
+C 100 ; WX 494 ; N delta ; B 40 -19 481 740 ;
+C 101 ; WX 439 ; N epsilon ; B 22 -19 427 502 ;
+C 102 ; WX 521 ; N phi ; B 27 -224 490 671 ;
+C 103 ; WX 411 ; N gamma ; B 5 -225 484 499 ;
+C 104 ; WX 603 ; N eta ; B 0 -202 527 514 ;
+C 105 ; WX 329 ; N iota ; B 0 -17 301 503 ;
+C 106 ; WX 603 ; N phi1 ; B 36 -224 587 499 ;
+C 107 ; WX 549 ; N kappa ; B 33 0 558 501 ;
+C 108 ; WX 549 ; N lambda ; B 24 -17 548 739 ;
+C 109 ; WX 576 ; N mu ; B 33 -223 567 500 ;
+C 110 ; WX 521 ; N nu ; B -9 -16 475 507 ;
+C 111 ; WX 549 ; N omicron ; B 35 -19 501 499 ;
+C 112 ; WX 549 ; N pi ; B 10 -19 530 487 ;
+C 113 ; WX 521 ; N theta ; B 43 -17 485 690 ;
+C 114 ; WX 549 ; N rho ; B 50 -230 490 499 ;
+C 115 ; WX 603 ; N sigma ; B 30 -21 588 500 ;
+C 116 ; WX 439 ; N tau ; B 10 -19 418 500 ;
+C 117 ; WX 576 ; N upsilon ; B 7 -18 535 507 ;
+C 118 ; WX 713 ; N omega1 ; B 12 -18 671 583 ;
+C 119 ; WX 686 ; N omega ; B 42 -17 684 500 ;
+C 120 ; WX 493 ; N xi ; B 27 -224 469 766 ;
+C 121 ; WX 686 ; N psi ; B 12 -228 701 500 ;
+C 122 ; WX 494 ; N zeta ; B 60 -225 467 756 ;
+C 123 ; WX 480 ; N braceleft ; B 58 -183 397 673 ;
+C 124 ; WX 200 ; N bar ; B 65 -177 135 673 ;
+C 125 ; WX 480 ; N braceright ; B 79 -183 418 673 ;
+C 126 ; WX 549 ; N similar ; B 17 203 529 307 ;
+C 161 ; WX 620 ; N Upsilon1 ; B -2 0 610 685 ;
+C 162 ; WX 247 ; N minute ; B 27 459 228 735 ;
+C 163 ; WX 549 ; N lessequal ; B 29 0 526 639 ;
+C 164 ; WX 167 ; N fraction ; B -180 -12 340 677 ;
+C 165 ; WX 713 ; N infinity ; B 26 124 688 404 ;
+C 166 ; WX 500 ; N florin ; B 2 -193 494 686 ;
+C 167 ; WX 753 ; N club ; B 86 -26 660 533 ;
+C 168 ; WX 753 ; N diamond ; B 142 -36 600 550 ;
+C 169 ; WX 753 ; N heart ; B 117 -33 631 532 ;
+C 170 ; WX 753 ; N spade ; B 113 -36 629 548 ;
+C 171 ; WX 1042 ; N arrowboth ; B 24 -15 1024 511 ;
+C 172 ; WX 987 ; N arrowleft ; B 32 -15 942 511 ;
+C 173 ; WX 603 ; N arrowup ; B 45 0 571 910 ;
+C 174 ; WX 987 ; N arrowright ; B 49 -15 959 511 ;
+C 175 ; WX 603 ; N arrowdown ; B 45 -22 571 888 ;
+C 176 ; WX 400 ; N degree ; B 50 385 350 685 ;
+C 177 ; WX 549 ; N plusminus ; B 10 0 539 645 ;
+C 178 ; WX 411 ; N second ; B 20 459 413 737 ;
+C 179 ; WX 549 ; N greaterequal ; B 29 0 526 639 ;
+C 180 ; WX 549 ; N multiply ; B 17 8 533 524 ;
+C 181 ; WX 713 ; N proportional ; B 27 123 639 404 ;
+C 182 ; WX 494 ; N partialdiff ; B 26 -20 462 746 ;
+C 183 ; WX 460 ; N bullet ; B 50 113 410 473 ;
+C 184 ; WX 549 ; N divide ; B 10 71 536 456 ;
+C 185 ; WX 549 ; N notequal ; B 15 -25 540 549 ;
+C 186 ; WX 549 ; N equivalence ; B 14 82 538 443 ;
+C 187 ; WX 549 ; N approxequal ; B 14 135 527 394 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -17 889 95 ;
+C 189 ; WX 603 ; N arrowvertex ; B 280 -120 336 1010 ;
+C 190 ; WX 1000 ; N arrowhorizex ; B -60 220 1050 276 ;
+C 191 ; WX 658 ; N carriagereturn ; B 15 -16 602 629 ;
+C 192 ; WX 823 ; N aleph ; B 175 -18 661 658 ;
+C 193 ; WX 686 ; N Ifraktur ; B 10 -53 578 740 ;
+C 194 ; WX 795 ; N Rfraktur ; B 26 -15 759 734 ;
+C 195 ; WX 987 ; N weierstrass ; B 159 -211 870 573 ;
+C 196 ; WX 768 ; N circlemultiply ; B 43 -17 733 673 ;
+C 197 ; WX 768 ; N circleplus ; B 43 -15 733 675 ;
+C 198 ; WX 823 ; N emptyset ; B 39 -24 781 719 ;
+C 199 ; WX 768 ; N intersection ; B 40 0 732 509 ;
+C 200 ; WX 768 ; N union ; B 40 -17 732 492 ;
+C 201 ; WX 713 ; N propersuperset ; B 20 0 673 470 ;
+C 202 ; WX 713 ; N reflexsuperset ; B 20 -125 673 470 ;
+C 203 ; WX 713 ; N notsubset ; B 36 -70 690 540 ;
+C 204 ; WX 713 ; N propersubset ; B 37 0 690 470 ;
+C 205 ; WX 713 ; N reflexsubset ; B 37 -125 690 470 ;
+C 206 ; WX 713 ; N element ; B 45 0 505 468 ;
+C 207 ; WX 713 ; N notelement ; B 45 -58 505 555 ;
+C 208 ; WX 768 ; N angle ; B 26 0 738 673 ;
+C 209 ; WX 713 ; N gradient ; B 36 -19 681 718 ;
+C 210 ; WX 790 ; N registerserif ; B 50 -17 740 673 ;
+C 211 ; WX 790 ; N copyrightserif ; B 51 -15 741 675 ;
+C 212 ; WX 890 ; N trademarkserif ; B 18 293 855 673 ;
+C 213 ; WX 823 ; N product ; B 25 -101 803 751 ;
+C 214 ; WX 549 ; N radical ; B 10 -38 515 917 ;
+C 215 ; WX 250 ; N dotmath ; B 69 210 169 310 ;
+C 216 ; WX 713 ; N logicalnot ; B 15 0 680 288 ;
+C 217 ; WX 603 ; N logicaland ; B 23 0 583 454 ;
+C 218 ; WX 603 ; N logicalor ; B 30 0 578 477 ;
+C 219 ; WX 1042 ; N arrowdblboth ; B 27 -20 1023 510 ;
+C 220 ; WX 987 ; N arrowdblleft ; B 30 -15 939 513 ;
+C 221 ; WX 603 ; N arrowdblup ; B 39 2 567 911 ;
+C 222 ; WX 987 ; N arrowdblright ; B 45 -20 954 508 ;
+C 223 ; WX 603 ; N arrowdbldown ; B 44 -19 572 890 ;
+C 224 ; WX 494 ; N lozenge ; B 18 0 466 745 ;
+C 225 ; WX 329 ; N angleleft ; B 25 -198 306 746 ;
+C 226 ; WX 790 ; N registersans ; B 50 -20 740 670 ;
+C 227 ; WX 790 ; N copyrightsans ; B 49 -15 739 675 ;
+C 228 ; WX 786 ; N trademarksans ; B 5 293 725 673 ;
+C 229 ; WX 713 ; N summation ; B 14 -108 695 752 ;
+C 230 ; WX 384 ; N parenlefttp ; B 40 -293 436 926 ;
+C 231 ; WX 384 ; N parenleftex ; B 40 -85 92 925 ;
+C 232 ; WX 384 ; N parenleftbt ; B 40 -293 436 926 ;
+C 233 ; WX 384 ; N bracketlefttp ; B 0 -80 341 926 ;
+C 234 ; WX 384 ; N bracketleftex ; B 0 -79 55 925 ;
+C 235 ; WX 384 ; N bracketleftbt ; B 0 -80 340 926 ;
+C 236 ; WX 494 ; N bracelefttp ; B 201 -75 439 926 ;
+C 237 ; WX 494 ; N braceleftmid ; B 14 -85 255 935 ;
+C 238 ; WX 494 ; N braceleftbt ; B 201 -70 439 926 ;
+C 239 ; WX 494 ; N braceex ; B 201 -80 255 935 ;
+C 241 ; WX 329 ; N angleright ; B 21 -198 302 746 ;
+C 242 ; WX 274 ; N integral ; B 2 -107 291 916 ;
+C 243 ; WX 686 ; N integraltp ; B 332 -83 715 921 ;
+C 244 ; WX 686 ; N integralex ; B 332 -88 415 975 ;
+C 245 ; WX 686 ; N integralbt ; B 39 -81 415 921 ;
+C 246 ; WX 384 ; N parenrighttp ; B 54 -293 450 926 ;
+C 247 ; WX 384 ; N parenrightex ; B 398 -85 450 925 ;
+C 248 ; WX 384 ; N parenrightbt ; B 54 -293 450 926 ;
+C 249 ; WX 384 ; N bracketrighttp ; B 22 -80 360 926 ;
+C 250 ; WX 384 ; N bracketrightex ; B 305 -79 360 925 ;
+C 251 ; WX 384 ; N bracketrightbt ; B 20 -80 360 926 ;
+C 252 ; WX 494 ; N bracerighttp ; B 17 -75 255 926 ;
+C 253 ; WX 494 ; N bracerightmid ; B 201 -85 442 935 ;
+C 254 ; WX 494 ; N bracerightbt ; B 17 -70 255 926 ;
+C -1 ; WX 790 ; N apple ; B 56 -3 733 808 ;
+EndCharMetrics
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Times-Bold.afm b/tlt3.0/library/afm/Times-Bold.afm
new file mode 100644
index 0000000..6ee7ef6
--- /dev/null
+++ b/tlt3.0/library/afm/Times-Bold.afm
@@ -0,0 +1,649 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Mar 20 12:17:14 1990
+Comment UniqueID 28417
+Comment VMusage 30458 37350
+FontName Times-Bold
+FullName Times Bold
+FamilyName Times
+Weight Bold
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -168 -218 1000 935
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 676
+XHeight 461
+Ascender 676
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 81 -13 251 691 ;
+C 34 ; WX 555 ; N quotedbl ; B 83 404 472 691 ;
+C 35 ; WX 500 ; N numbersign ; B 4 0 496 700 ;
+C 36 ; WX 500 ; N dollar ; B 29 -99 472 750 ;
+C 37 ; WX 1000 ; N percent ; B 124 -14 877 692 ;
+C 38 ; WX 833 ; N ampersand ; B 62 -16 787 691 ;
+C 39 ; WX 333 ; N quoteright ; B 79 356 263 691 ;
+C 40 ; WX 333 ; N parenleft ; B 46 -168 306 694 ;
+C 41 ; WX 333 ; N parenright ; B 27 -168 287 694 ;
+C 42 ; WX 500 ; N asterisk ; B 56 255 447 691 ;
+C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
+C 44 ; WX 250 ; N comma ; B 39 -180 223 155 ;
+C 45 ; WX 333 ; N hyphen ; B 44 171 287 287 ;
+C 46 ; WX 250 ; N period ; B 41 -13 210 156 ;
+C 47 ; WX 278 ; N slash ; B -24 -19 302 691 ;
+C 48 ; WX 500 ; N zero ; B 24 -13 476 688 ;
+C 49 ; WX 500 ; N one ; B 65 0 442 688 ;
+C 50 ; WX 500 ; N two ; B 17 0 478 688 ;
+C 51 ; WX 500 ; N three ; B 16 -14 468 688 ;
+C 52 ; WX 500 ; N four ; B 19 0 475 688 ;
+C 53 ; WX 500 ; N five ; B 22 -8 470 676 ;
+C 54 ; WX 500 ; N six ; B 28 -13 475 688 ;
+C 55 ; WX 500 ; N seven ; B 17 0 477 676 ;
+C 56 ; WX 500 ; N eight ; B 28 -13 472 688 ;
+C 57 ; WX 500 ; N nine ; B 26 -13 473 688 ;
+C 58 ; WX 333 ; N colon ; B 82 -13 251 472 ;
+C 59 ; WX 333 ; N semicolon ; B 82 -180 266 472 ;
+C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
+C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
+C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
+C 63 ; WX 500 ; N question ; B 57 -13 445 689 ;
+C 64 ; WX 930 ; N at ; B 108 -19 822 691 ;
+C 65 ; WX 722 ; N A ; B 9 0 689 690 ;
+C 66 ; WX 667 ; N B ; B 16 0 619 676 ;
+C 67 ; WX 722 ; N C ; B 49 -19 687 691 ;
+C 68 ; WX 722 ; N D ; B 14 0 690 676 ;
+C 69 ; WX 667 ; N E ; B 16 0 641 676 ;
+C 70 ; WX 611 ; N F ; B 16 0 583 676 ;
+C 71 ; WX 778 ; N G ; B 37 -19 755 691 ;
+C 72 ; WX 778 ; N H ; B 21 0 759 676 ;
+C 73 ; WX 389 ; N I ; B 20 0 370 676 ;
+C 74 ; WX 500 ; N J ; B 3 -96 479 676 ;
+C 75 ; WX 778 ; N K ; B 30 0 769 676 ;
+C 76 ; WX 667 ; N L ; B 19 0 638 676 ;
+C 77 ; WX 944 ; N M ; B 14 0 921 676 ;
+C 78 ; WX 722 ; N N ; B 16 -18 701 676 ;
+C 79 ; WX 778 ; N O ; B 35 -19 743 691 ;
+C 80 ; WX 611 ; N P ; B 16 0 600 676 ;
+C 81 ; WX 778 ; N Q ; B 35 -176 743 691 ;
+C 82 ; WX 722 ; N R ; B 26 0 715 676 ;
+C 83 ; WX 556 ; N S ; B 35 -19 513 692 ;
+C 84 ; WX 667 ; N T ; B 31 0 636 676 ;
+C 85 ; WX 722 ; N U ; B 16 -19 701 676 ;
+C 86 ; WX 722 ; N V ; B 16 -18 701 676 ;
+C 87 ; WX 1000 ; N W ; B 19 -15 981 676 ;
+C 88 ; WX 722 ; N X ; B 16 0 699 676 ;
+C 89 ; WX 722 ; N Y ; B 15 0 699 676 ;
+C 90 ; WX 667 ; N Z ; B 28 0 634 676 ;
+C 91 ; WX 333 ; N bracketleft ; B 67 -149 301 678 ;
+C 92 ; WX 278 ; N backslash ; B -25 -19 303 691 ;
+C 93 ; WX 333 ; N bracketright ; B 32 -149 266 678 ;
+C 94 ; WX 581 ; N asciicircum ; B 73 311 509 676 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 70 356 254 691 ;
+C 97 ; WX 500 ; N a ; B 25 -14 488 473 ;
+C 98 ; WX 556 ; N b ; B 17 -14 521 676 ;
+C 99 ; WX 444 ; N c ; B 25 -14 430 473 ;
+C 100 ; WX 556 ; N d ; B 25 -14 534 676 ;
+C 101 ; WX 444 ; N e ; B 25 -14 426 473 ;
+C 102 ; WX 333 ; N f ; B 14 0 389 691 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 28 -206 483 473 ;
+C 104 ; WX 556 ; N h ; B 16 0 534 676 ;
+C 105 ; WX 278 ; N i ; B 16 0 255 691 ;
+C 106 ; WX 333 ; N j ; B -57 -203 263 691 ;
+C 107 ; WX 556 ; N k ; B 22 0 543 676 ;
+C 108 ; WX 278 ; N l ; B 16 0 255 676 ;
+C 109 ; WX 833 ; N m ; B 16 0 814 473 ;
+C 110 ; WX 556 ; N n ; B 21 0 539 473 ;
+C 111 ; WX 500 ; N o ; B 25 -14 476 473 ;
+C 112 ; WX 556 ; N p ; B 19 -205 524 473 ;
+C 113 ; WX 556 ; N q ; B 34 -205 536 473 ;
+C 114 ; WX 444 ; N r ; B 29 0 434 473 ;
+C 115 ; WX 389 ; N s ; B 25 -14 361 473 ;
+C 116 ; WX 333 ; N t ; B 20 -12 332 630 ;
+C 117 ; WX 556 ; N u ; B 16 -14 537 461 ;
+C 118 ; WX 500 ; N v ; B 21 -14 485 461 ;
+C 119 ; WX 722 ; N w ; B 23 -14 707 461 ;
+C 120 ; WX 500 ; N x ; B 12 0 484 461 ;
+C 121 ; WX 500 ; N y ; B 16 -205 480 461 ;
+C 122 ; WX 444 ; N z ; B 21 0 420 461 ;
+C 123 ; WX 394 ; N braceleft ; B 22 -175 340 698 ;
+C 124 ; WX 220 ; N bar ; B 66 -19 154 691 ;
+C 125 ; WX 394 ; N braceright ; B 54 -175 372 698 ;
+C 126 ; WX 520 ; N asciitilde ; B 29 173 491 333 ;
+C 161 ; WX 333 ; N exclamdown ; B 82 -203 252 501 ;
+C 162 ; WX 500 ; N cent ; B 53 -140 458 588 ;
+C 163 ; WX 500 ; N sterling ; B 21 -14 477 684 ;
+C 164 ; WX 167 ; N fraction ; B -168 -12 329 688 ;
+C 165 ; WX 500 ; N yen ; B -64 0 547 676 ;
+C 166 ; WX 500 ; N florin ; B 0 -155 498 706 ;
+C 167 ; WX 500 ; N section ; B 57 -132 443 691 ;
+C 168 ; WX 500 ; N currency ; B -26 61 526 613 ;
+C 169 ; WX 278 ; N quotesingle ; B 75 404 204 691 ;
+C 170 ; WX 500 ; N quotedblleft ; B 32 356 486 691 ;
+C 171 ; WX 500 ; N guillemotleft ; B 23 36 473 415 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 51 36 305 415 ;
+C 173 ; WX 333 ; N guilsinglright ; B 28 36 282 415 ;
+C 174 ; WX 556 ; N fi ; B 14 0 536 691 ;
+C 175 ; WX 556 ; N fl ; B 14 0 536 691 ;
+C 177 ; WX 500 ; N endash ; B 0 181 500 271 ;
+C 178 ; WX 500 ; N dagger ; B 47 -134 453 691 ;
+C 179 ; WX 500 ; N daggerdbl ; B 45 -132 456 691 ;
+C 180 ; WX 250 ; N periodcentered ; B 41 248 210 417 ;
+C 182 ; WX 540 ; N paragraph ; B 0 -186 519 676 ;
+C 183 ; WX 350 ; N bullet ; B 35 198 315 478 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 79 -180 263 155 ;
+C 185 ; WX 500 ; N quotedblbase ; B 14 -180 468 155 ;
+C 186 ; WX 500 ; N quotedblright ; B 14 356 468 691 ;
+C 187 ; WX 500 ; N guillemotright ; B 27 36 477 415 ;
+C 188 ; WX 1000 ; N ellipsis ; B 82 -13 917 156 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -29 995 706 ;
+C 191 ; WX 500 ; N questiondown ; B 55 -201 443 501 ;
+C 193 ; WX 333 ; N grave ; B 8 528 246 713 ;
+C 194 ; WX 333 ; N acute ; B 86 528 324 713 ;
+C 195 ; WX 333 ; N circumflex ; B -2 528 335 704 ;
+C 196 ; WX 333 ; N tilde ; B -16 547 349 674 ;
+C 197 ; WX 333 ; N macron ; B 1 565 331 637 ;
+C 198 ; WX 333 ; N breve ; B 15 528 318 691 ;
+C 199 ; WX 333 ; N dotaccent ; B 103 537 230 667 ;
+C 200 ; WX 333 ; N dieresis ; B -2 537 335 667 ;
+C 202 ; WX 333 ; N ring ; B 60 527 273 740 ;
+C 203 ; WX 333 ; N cedilla ; B 68 -218 294 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -13 528 425 713 ;
+C 206 ; WX 333 ; N ogonek ; B 90 -173 319 44 ;
+C 207 ; WX 333 ; N caron ; B -2 528 335 704 ;
+C 208 ; WX 1000 ; N emdash ; B 0 181 1000 271 ;
+C 225 ; WX 1000 ; N AE ; B 4 0 951 676 ;
+C 227 ; WX 300 ; N ordfeminine ; B -1 397 301 688 ;
+C 232 ; WX 667 ; N Lslash ; B 19 0 638 676 ;
+C 233 ; WX 778 ; N Oslash ; B 35 -74 743 737 ;
+C 234 ; WX 1000 ; N OE ; B 22 -5 981 684 ;
+C 235 ; WX 330 ; N ordmasculine ; B 18 397 312 688 ;
+C 241 ; WX 722 ; N ae ; B 33 -14 693 473 ;
+C 245 ; WX 278 ; N dotlessi ; B 16 0 255 461 ;
+C 248 ; WX 278 ; N lslash ; B -22 0 303 676 ;
+C 249 ; WX 500 ; N oslash ; B 25 -92 476 549 ;
+C 250 ; WX 722 ; N oe ; B 22 -14 696 473 ;
+C 251 ; WX 556 ; N germandbls ; B 19 -12 517 691 ;
+C -1 ; WX 667 ; N Zcaron ; B 28 0 634 914 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -218 430 473 ;
+C -1 ; WX 500 ; N ydieresis ; B 16 -205 480 667 ;
+C -1 ; WX 500 ; N atilde ; B 25 -14 488 674 ;
+C -1 ; WX 278 ; N icircumflex ; B -36 0 301 704 ;
+C -1 ; WX 300 ; N threesuperior ; B 3 268 297 688 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -14 426 704 ;
+C -1 ; WX 556 ; N thorn ; B 19 -205 524 676 ;
+C -1 ; WX 444 ; N egrave ; B 25 -14 426 713 ;
+C -1 ; WX 300 ; N twosuperior ; B 0 275 300 688 ;
+C -1 ; WX 444 ; N eacute ; B 25 -14 426 713 ;
+C -1 ; WX 500 ; N otilde ; B 25 -14 476 674 ;
+C -1 ; WX 722 ; N Aacute ; B 9 0 689 923 ;
+C -1 ; WX 500 ; N ocircumflex ; B 25 -14 476 704 ;
+C -1 ; WX 500 ; N yacute ; B 16 -205 480 713 ;
+C -1 ; WX 556 ; N udieresis ; B 16 -14 537 667 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -12 733 688 ;
+C -1 ; WX 500 ; N acircumflex ; B 25 -14 488 704 ;
+C -1 ; WX 722 ; N Eth ; B 6 0 690 676 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -14 426 667 ;
+C -1 ; WX 556 ; N ugrave ; B 16 -14 537 713 ;
+C -1 ; WX 1000 ; N trademark ; B 24 271 977 676 ;
+C -1 ; WX 500 ; N ograve ; B 25 -14 476 713 ;
+C -1 ; WX 389 ; N scaron ; B 25 -14 363 704 ;
+C -1 ; WX 389 ; N Idieresis ; B 20 0 370 877 ;
+C -1 ; WX 556 ; N uacute ; B 16 -14 537 713 ;
+C -1 ; WX 500 ; N agrave ; B 25 -14 488 713 ;
+C -1 ; WX 556 ; N ntilde ; B 21 0 539 674 ;
+C -1 ; WX 500 ; N aring ; B 25 -14 488 740 ;
+C -1 ; WX 444 ; N zcaron ; B 21 0 420 704 ;
+C -1 ; WX 389 ; N Icircumflex ; B 20 0 370 914 ;
+C -1 ; WX 722 ; N Ntilde ; B 16 -18 701 884 ;
+C -1 ; WX 556 ; N ucircumflex ; B 16 -14 537 704 ;
+C -1 ; WX 667 ; N Ecircumflex ; B 16 0 641 914 ;
+C -1 ; WX 389 ; N Iacute ; B 20 0 370 923 ;
+C -1 ; WX 722 ; N Ccedilla ; B 49 -218 687 691 ;
+C -1 ; WX 778 ; N Odieresis ; B 35 -19 743 877 ;
+C -1 ; WX 556 ; N Scaron ; B 35 -19 513 914 ;
+C -1 ; WX 667 ; N Edieresis ; B 16 0 641 877 ;
+C -1 ; WX 389 ; N Igrave ; B 20 0 370 923 ;
+C -1 ; WX 500 ; N adieresis ; B 25 -14 488 667 ;
+C -1 ; WX 778 ; N Ograve ; B 35 -19 743 923 ;
+C -1 ; WX 667 ; N Egrave ; B 16 0 641 923 ;
+C -1 ; WX 722 ; N Ydieresis ; B 15 0 699 877 ;
+C -1 ; WX 747 ; N registered ; B 26 -19 721 691 ;
+C -1 ; WX 778 ; N Otilde ; B 35 -19 743 884 ;
+C -1 ; WX 750 ; N onequarter ; B 28 -12 743 688 ;
+C -1 ; WX 722 ; N Ugrave ; B 16 -19 701 923 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 16 -19 701 914 ;
+C -1 ; WX 611 ; N Thorn ; B 16 0 600 676 ;
+C -1 ; WX 570 ; N divide ; B 33 -31 537 537 ;
+C -1 ; WX 722 ; N Atilde ; B 9 0 689 884 ;
+C -1 ; WX 722 ; N Uacute ; B 16 -19 701 923 ;
+C -1 ; WX 778 ; N Ocircumflex ; B 35 -19 743 914 ;
+C -1 ; WX 570 ; N logicalnot ; B 33 108 537 399 ;
+C -1 ; WX 722 ; N Aring ; B 9 0 689 935 ;
+C -1 ; WX 278 ; N idieresis ; B -36 0 301 667 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 290 713 ;
+C -1 ; WX 500 ; N aacute ; B 25 -14 488 713 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 722 ; N Udieresis ; B 16 -19 701 877 ;
+C -1 ; WX 570 ; N minus ; B 33 209 537 297 ;
+C -1 ; WX 300 ; N onesuperior ; B 28 275 273 688 ;
+C -1 ; WX 667 ; N Eacute ; B 16 0 641 923 ;
+C -1 ; WX 722 ; N Acircumflex ; B 9 0 689 914 ;
+C -1 ; WX 747 ; N copyright ; B 26 -19 721 691 ;
+C -1 ; WX 722 ; N Agrave ; B 9 0 689 923 ;
+C -1 ; WX 500 ; N odieresis ; B 25 -14 476 667 ;
+C -1 ; WX 500 ; N oacute ; B 25 -14 476 713 ;
+C -1 ; WX 400 ; N degree ; B 57 402 343 688 ;
+C -1 ; WX 278 ; N igrave ; B -26 0 255 713 ;
+C -1 ; WX 556 ; N mu ; B 33 -206 536 461 ;
+C -1 ; WX 778 ; N Oacute ; B 35 -19 743 923 ;
+C -1 ; WX 500 ; N eth ; B 25 -14 476 691 ;
+C -1 ; WX 722 ; N Adieresis ; B 9 0 689 877 ;
+C -1 ; WX 722 ; N Yacute ; B 15 0 699 928 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -19 154 691 ;
+C -1 ; WX 750 ; N onehalf ; B -7 -12 775 688 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 283
+
+KPX A y -74
+KPX A w -90
+KPX A v -100
+KPX A u -50
+KPX A quoteright -74
+KPX A quotedblright 0
+KPX A p -25
+KPX A Y -100
+KPX A W -130
+KPX A V -145
+KPX A U -50
+KPX A T -95
+KPX A Q -45
+KPX A O -45
+KPX A G -55
+KPX A C -55
+
+KPX B period 0
+KPX B comma 0
+KPX B U -10
+KPX B A -30
+
+KPX D period -20
+KPX D comma 0
+KPX D Y -40
+KPX D W -40
+KPX D V -40
+KPX D A -35
+
+KPX F r 0
+KPX F period -110
+KPX F o -25
+KPX F i 0
+KPX F e -25
+KPX F comma -92
+KPX F a -25
+KPX F A -90
+
+KPX G period 0
+KPX G comma 0
+
+KPX J u -15
+KPX J period -20
+KPX J o -15
+KPX J e -15
+KPX J comma 0
+KPX J a -15
+KPX J A -30
+
+KPX K y -45
+KPX K u -15
+KPX K o -25
+KPX K e -25
+KPX K O -30
+
+KPX L y -55
+KPX L quoteright -110
+KPX L quotedblright -20
+KPX L Y -92
+KPX L W -92
+KPX L V -92
+KPX L T -92
+
+KPX N period 0
+KPX N comma 0
+KPX N A -20
+
+KPX O period 0
+KPX O comma 0
+KPX O Y -50
+KPX O X -40
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -40
+
+KPX P period -110
+KPX P o -20
+KPX P e -20
+KPX P comma -92
+KPX P a -10
+KPX P A -74
+
+KPX Q period -20
+KPX Q comma 0
+KPX Q U -10
+
+KPX R Y -35
+KPX R W -35
+KPX R V -55
+KPX R U -30
+KPX R T -40
+KPX R O -30
+
+KPX S period 0
+KPX S comma 0
+
+KPX T y -74
+KPX T w -74
+KPX T u -92
+KPX T semicolon -74
+KPX T r -74
+KPX T period -90
+KPX T o -92
+KPX T i -18
+KPX T hyphen -92
+KPX T h 0
+KPX T e -92
+KPX T comma -74
+KPX T colon -74
+KPX T a -92
+KPX T O -18
+KPX T A -90
+
+KPX U period -50
+KPX U comma -50
+KPX U A -60
+
+KPX V u -92
+KPX V semicolon -92
+KPX V period -145
+KPX V o -100
+KPX V i -37
+KPX V hyphen -74
+KPX V e -100
+KPX V comma -129
+KPX V colon -92
+KPX V a -92
+KPX V O -45
+KPX V G -30
+KPX V A -135
+
+KPX W y -60
+KPX W u -50
+KPX W semicolon -55
+KPX W period -92
+KPX W o -75
+KPX W i -18
+KPX W hyphen -37
+KPX W h 0
+KPX W e -65
+KPX W comma -92
+KPX W colon -55
+KPX W a -65
+KPX W O -10
+KPX W A -120
+
+KPX Y u -92
+KPX Y semicolon -92
+KPX Y period -92
+KPX Y o -111
+KPX Y i -37
+KPX Y hyphen -92
+KPX Y e -111
+KPX Y comma -92
+KPX Y colon -92
+KPX Y a -85
+KPX Y O -35
+KPX Y A -110
+
+KPX a y 0
+KPX a w 0
+KPX a v -25
+KPX a t 0
+KPX a p 0
+KPX a g 0
+KPX a b 0
+
+KPX b y 0
+KPX b v -15
+KPX b u -20
+KPX b period -40
+KPX b l 0
+KPX b comma 0
+KPX b b -10
+
+KPX c y 0
+KPX c period 0
+KPX c l 0
+KPX c k 0
+KPX c h 0
+KPX c comma 0
+
+KPX colon space 0
+
+KPX comma space 0
+KPX comma quoteright -55
+KPX comma quotedblright -45
+
+KPX d y 0
+KPX d w -15
+KPX d v 0
+KPX d period 0
+KPX d d 0
+KPX d comma 0
+
+KPX e y 0
+KPX e x 0
+KPX e w 0
+KPX e v -15
+KPX e period 0
+KPX e p 0
+KPX e g 0
+KPX e comma 0
+KPX e b 0
+
+KPX f quoteright 55
+KPX f quotedblright 50
+KPX f period -15
+KPX f o -25
+KPX f l 0
+KPX f i -25
+KPX f f 0
+KPX f e 0
+KPX f dotlessi -35
+KPX f comma -15
+KPX f a 0
+
+KPX g y 0
+KPX g r 0
+KPX g period -15
+KPX g o 0
+KPX g i 0
+KPX g g 0
+KPX g e 0
+KPX g comma 0
+KPX g a 0
+
+KPX h y -15
+
+KPX i v -10
+
+KPX k y -15
+KPX k o -15
+KPX k e -10
+
+KPX l y 0
+KPX l w 0
+
+KPX m y 0
+KPX m u 0
+
+KPX n y 0
+KPX n v -40
+KPX n u 0
+
+KPX o y 0
+KPX o x 0
+KPX o w -10
+KPX o v -10
+KPX o g 0
+
+KPX p y 0
+
+KPX period quoteright -55
+KPX period quotedblright -55
+
+KPX quotedblleft quoteleft 0
+KPX quotedblleft A -10
+
+KPX quotedblright space 0
+
+KPX quoteleft quoteleft -63
+KPX quoteleft A -10
+
+KPX quoteright v -20
+KPX quoteright t 0
+KPX quoteright space -74
+KPX quoteright s -37
+KPX quoteright r -20
+KPX quoteright quoteright -63
+KPX quoteright quotedblright 0
+KPX quoteright l 0
+KPX quoteright d -20
+
+KPX r y 0
+KPX r v -10
+KPX r u 0
+KPX r t 0
+KPX r s 0
+KPX r r 0
+KPX r q -18
+KPX r period -100
+KPX r p -10
+KPX r o -18
+KPX r n -15
+KPX r m 0
+KPX r l 0
+KPX r k 0
+KPX r i 0
+KPX r hyphen -37
+KPX r g -10
+KPX r e -18
+KPX r d 0
+KPX r comma -92
+KPX r c -18
+KPX r a 0
+
+KPX s w 0
+
+KPX space quoteleft 0
+KPX space quotedblleft 0
+KPX space Y -55
+KPX space W -30
+KPX space V -45
+KPX space T -30
+KPX space A -55
+
+KPX v period -70
+KPX v o -10
+KPX v e -10
+KPX v comma -55
+KPX v a -10
+
+KPX w period -70
+KPX w o -10
+KPX w h 0
+KPX w e 0
+KPX w comma -55
+KPX w a 0
+
+KPX x e 0
+
+KPX y period -70
+KPX y o -25
+KPX y e -10
+KPX y comma -55
+KPX y a 0
+
+KPX z o 0
+KPX z e 0
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 188 210 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 188 210 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 188 210 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 188 210 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 180 195 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 188 210 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 208 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 174 210 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 174 210 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 174 210 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 174 210 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 28 210 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 28 210 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 28 210 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 28 210 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 210 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 223 210 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 223 210 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 223 210 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 223 210 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 223 210 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 210 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 222 210 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 222 210 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 222 210 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 222 210 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 210 215 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 215 210 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 167 210 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 77 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 77 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 77 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 77 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 77 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 77 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 69 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 62 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 62 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 62 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 62 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -34 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -34 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -34 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -34 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 112 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 105 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 105 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 105 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 105 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 56 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Times-BoldItalic.afm b/tlt3.0/library/afm/Times-BoldItalic.afm
new file mode 100644
index 0000000..d329ebb
--- /dev/null
+++ b/tlt3.0/library/afm/Times-BoldItalic.afm
@@ -0,0 +1,649 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Mar 20 13:14:55 1990
+Comment UniqueID 28425
+Comment VMusage 32721 39613
+FontName Times-BoldItalic
+FullName Times Bold Italic
+FamilyName Times
+Weight Bold
+ItalicAngle -15
+IsFixedPitch false
+FontBBox -200 -218 996 921
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.009
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 669
+XHeight 462
+Ascender 699
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 389 ; N exclam ; B 67 -13 370 684 ;
+C 34 ; WX 555 ; N quotedbl ; B 136 398 536 685 ;
+C 35 ; WX 500 ; N numbersign ; B -33 0 533 700 ;
+C 36 ; WX 500 ; N dollar ; B -20 -100 497 733 ;
+C 37 ; WX 833 ; N percent ; B 39 -10 793 692 ;
+C 38 ; WX 778 ; N ampersand ; B 5 -19 699 682 ;
+C 39 ; WX 333 ; N quoteright ; B 98 369 302 685 ;
+C 40 ; WX 333 ; N parenleft ; B 28 -179 344 685 ;
+C 41 ; WX 333 ; N parenright ; B -44 -179 271 685 ;
+C 42 ; WX 500 ; N asterisk ; B 65 249 456 685 ;
+C 43 ; WX 570 ; N plus ; B 33 0 537 506 ;
+C 44 ; WX 250 ; N comma ; B -60 -182 144 134 ;
+C 45 ; WX 333 ; N hyphen ; B 2 166 271 282 ;
+C 46 ; WX 250 ; N period ; B -9 -13 139 135 ;
+C 47 ; WX 278 ; N slash ; B -64 -18 342 685 ;
+C 48 ; WX 500 ; N zero ; B 17 -14 477 683 ;
+C 49 ; WX 500 ; N one ; B 5 0 419 683 ;
+C 50 ; WX 500 ; N two ; B -27 0 446 683 ;
+C 51 ; WX 500 ; N three ; B -15 -13 450 683 ;
+C 52 ; WX 500 ; N four ; B -15 0 503 683 ;
+C 53 ; WX 500 ; N five ; B -11 -13 487 669 ;
+C 54 ; WX 500 ; N six ; B 23 -15 509 679 ;
+C 55 ; WX 500 ; N seven ; B 52 0 525 669 ;
+C 56 ; WX 500 ; N eight ; B 3 -13 476 683 ;
+C 57 ; WX 500 ; N nine ; B -12 -10 475 683 ;
+C 58 ; WX 333 ; N colon ; B 23 -13 264 459 ;
+C 59 ; WX 333 ; N semicolon ; B -25 -183 264 459 ;
+C 60 ; WX 570 ; N less ; B 31 -8 539 514 ;
+C 61 ; WX 570 ; N equal ; B 33 107 537 399 ;
+C 62 ; WX 570 ; N greater ; B 31 -8 539 514 ;
+C 63 ; WX 500 ; N question ; B 79 -13 470 684 ;
+C 64 ; WX 832 ; N at ; B 63 -18 770 685 ;
+C 65 ; WX 667 ; N A ; B -67 0 593 683 ;
+C 66 ; WX 667 ; N B ; B -24 0 624 669 ;
+C 67 ; WX 667 ; N C ; B 32 -18 677 685 ;
+C 68 ; WX 722 ; N D ; B -46 0 685 669 ;
+C 69 ; WX 667 ; N E ; B -27 0 653 669 ;
+C 70 ; WX 667 ; N F ; B -13 0 660 669 ;
+C 71 ; WX 722 ; N G ; B 21 -18 706 685 ;
+C 72 ; WX 778 ; N H ; B -24 0 799 669 ;
+C 73 ; WX 389 ; N I ; B -32 0 406 669 ;
+C 74 ; WX 500 ; N J ; B -46 -99 524 669 ;
+C 75 ; WX 667 ; N K ; B -21 0 702 669 ;
+C 76 ; WX 611 ; N L ; B -22 0 590 669 ;
+C 77 ; WX 889 ; N M ; B -29 -12 917 669 ;
+C 78 ; WX 722 ; N N ; B -27 -15 748 669 ;
+C 79 ; WX 722 ; N O ; B 27 -18 691 685 ;
+C 80 ; WX 611 ; N P ; B -27 0 613 669 ;
+C 81 ; WX 722 ; N Q ; B 27 -208 691 685 ;
+C 82 ; WX 667 ; N R ; B -29 0 623 669 ;
+C 83 ; WX 556 ; N S ; B 2 -18 526 685 ;
+C 84 ; WX 611 ; N T ; B 50 0 650 669 ;
+C 85 ; WX 722 ; N U ; B 67 -18 744 669 ;
+C 86 ; WX 667 ; N V ; B 65 -18 715 669 ;
+C 87 ; WX 889 ; N W ; B 65 -18 940 669 ;
+C 88 ; WX 667 ; N X ; B -24 0 694 669 ;
+C 89 ; WX 611 ; N Y ; B 73 0 659 669 ;
+C 90 ; WX 611 ; N Z ; B -11 0 590 669 ;
+C 91 ; WX 333 ; N bracketleft ; B -37 -159 362 674 ;
+C 92 ; WX 278 ; N backslash ; B -1 -18 279 685 ;
+C 93 ; WX 333 ; N bracketright ; B -56 -157 343 674 ;
+C 94 ; WX 570 ; N asciicircum ; B 67 304 503 669 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 128 369 332 685 ;
+C 97 ; WX 500 ; N a ; B -21 -14 455 462 ;
+C 98 ; WX 500 ; N b ; B -14 -13 444 699 ;
+C 99 ; WX 444 ; N c ; B -5 -13 392 462 ;
+C 100 ; WX 500 ; N d ; B -21 -13 517 699 ;
+C 101 ; WX 444 ; N e ; B 5 -13 398 462 ;
+C 102 ; WX 333 ; N f ; B -169 -205 446 698 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B -52 -203 478 462 ;
+C 104 ; WX 556 ; N h ; B -13 -9 498 699 ;
+C 105 ; WX 278 ; N i ; B 2 -9 263 684 ;
+C 106 ; WX 278 ; N j ; B -189 -207 279 684 ;
+C 107 ; WX 500 ; N k ; B -23 -8 483 699 ;
+C 108 ; WX 278 ; N l ; B 2 -9 290 699 ;
+C 109 ; WX 778 ; N m ; B -14 -9 722 462 ;
+C 110 ; WX 556 ; N n ; B -6 -9 493 462 ;
+C 111 ; WX 500 ; N o ; B -3 -13 441 462 ;
+C 112 ; WX 500 ; N p ; B -120 -205 446 462 ;
+C 113 ; WX 500 ; N q ; B 1 -205 471 462 ;
+C 114 ; WX 389 ; N r ; B -21 0 389 462 ;
+C 115 ; WX 389 ; N s ; B -19 -13 333 462 ;
+C 116 ; WX 278 ; N t ; B -11 -9 281 594 ;
+C 117 ; WX 556 ; N u ; B 15 -9 492 462 ;
+C 118 ; WX 444 ; N v ; B 16 -13 401 462 ;
+C 119 ; WX 667 ; N w ; B 16 -13 614 462 ;
+C 120 ; WX 500 ; N x ; B -46 -13 469 462 ;
+C 121 ; WX 444 ; N y ; B -94 -205 392 462 ;
+C 122 ; WX 389 ; N z ; B -43 -78 368 449 ;
+C 123 ; WX 348 ; N braceleft ; B 5 -187 436 686 ;
+C 124 ; WX 220 ; N bar ; B 66 -18 154 685 ;
+C 125 ; WX 348 ; N braceright ; B -129 -187 302 686 ;
+C 126 ; WX 570 ; N asciitilde ; B 54 173 516 333 ;
+C 161 ; WX 389 ; N exclamdown ; B 19 -205 322 492 ;
+C 162 ; WX 500 ; N cent ; B 42 -143 439 576 ;
+C 163 ; WX 500 ; N sterling ; B -32 -12 510 683 ;
+C 164 ; WX 167 ; N fraction ; B -169 -14 324 683 ;
+C 165 ; WX 500 ; N yen ; B 33 0 628 669 ;
+C 166 ; WX 500 ; N florin ; B -87 -156 537 707 ;
+C 167 ; WX 500 ; N section ; B 36 -143 459 685 ;
+C 168 ; WX 500 ; N currency ; B -26 34 526 586 ;
+C 169 ; WX 278 ; N quotesingle ; B 128 398 268 685 ;
+C 170 ; WX 500 ; N quotedblleft ; B 53 369 513 685 ;
+C 171 ; WX 500 ; N guillemotleft ; B 12 32 468 415 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 32 32 303 415 ;
+C 173 ; WX 333 ; N guilsinglright ; B 10 32 281 415 ;
+C 174 ; WX 556 ; N fi ; B -188 -205 514 703 ;
+C 175 ; WX 556 ; N fl ; B -186 -205 553 704 ;
+C 177 ; WX 500 ; N endash ; B -40 178 477 269 ;
+C 178 ; WX 500 ; N dagger ; B 91 -145 494 685 ;
+C 179 ; WX 500 ; N daggerdbl ; B 10 -139 493 685 ;
+C 180 ; WX 250 ; N periodcentered ; B 51 257 199 405 ;
+C 182 ; WX 500 ; N paragraph ; B -57 -193 562 669 ;
+C 183 ; WX 350 ; N bullet ; B 0 175 350 525 ;
+C 184 ; WX 333 ; N quotesinglbase ; B -5 -182 199 134 ;
+C 185 ; WX 500 ; N quotedblbase ; B -57 -182 403 134 ;
+C 186 ; WX 500 ; N quotedblright ; B 53 369 513 685 ;
+C 187 ; WX 500 ; N guillemotright ; B 12 32 468 415 ;
+C 188 ; WX 1000 ; N ellipsis ; B 40 -13 852 135 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -29 996 706 ;
+C 191 ; WX 500 ; N questiondown ; B 30 -205 421 492 ;
+C 193 ; WX 333 ; N grave ; B 85 516 297 697 ;
+C 194 ; WX 333 ; N acute ; B 139 516 379 697 ;
+C 195 ; WX 333 ; N circumflex ; B 40 516 367 690 ;
+C 196 ; WX 333 ; N tilde ; B 48 536 407 655 ;
+C 197 ; WX 333 ; N macron ; B 51 553 393 623 ;
+C 198 ; WX 333 ; N breve ; B 71 516 387 678 ;
+C 199 ; WX 333 ; N dotaccent ; B 163 525 293 655 ;
+C 200 ; WX 333 ; N dieresis ; B 55 525 397 655 ;
+C 202 ; WX 333 ; N ring ; B 127 516 340 729 ;
+C 203 ; WX 333 ; N cedilla ; B -80 -218 156 5 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 69 516 498 697 ;
+C 206 ; WX 333 ; N ogonek ; B -40 -173 189 44 ;
+C 207 ; WX 333 ; N caron ; B 79 516 411 690 ;
+C 208 ; WX 1000 ; N emdash ; B -40 178 977 269 ;
+C 225 ; WX 944 ; N AE ; B -64 0 918 669 ;
+C 227 ; WX 266 ; N ordfeminine ; B 16 399 330 685 ;
+C 232 ; WX 611 ; N Lslash ; B -22 0 590 669 ;
+C 233 ; WX 722 ; N Oslash ; B 27 -125 691 764 ;
+C 234 ; WX 944 ; N OE ; B 23 -8 946 677 ;
+C 235 ; WX 300 ; N ordmasculine ; B 56 400 347 685 ;
+C 241 ; WX 722 ; N ae ; B -5 -13 673 462 ;
+C 245 ; WX 278 ; N dotlessi ; B 2 -9 238 462 ;
+C 248 ; WX 278 ; N lslash ; B -13 -9 301 699 ;
+C 249 ; WX 500 ; N oslash ; B -3 -119 441 560 ;
+C 250 ; WX 722 ; N oe ; B 6 -13 674 462 ;
+C 251 ; WX 500 ; N germandbls ; B -200 -200 473 705 ;
+C -1 ; WX 611 ; N Zcaron ; B -11 0 590 897 ;
+C -1 ; WX 444 ; N ccedilla ; B -24 -218 392 462 ;
+C -1 ; WX 444 ; N ydieresis ; B -94 -205 438 655 ;
+C -1 ; WX 500 ; N atilde ; B -21 -14 491 655 ;
+C -1 ; WX 278 ; N icircumflex ; B -2 -9 325 690 ;
+C -1 ; WX 300 ; N threesuperior ; B 17 265 321 683 ;
+C -1 ; WX 444 ; N ecircumflex ; B 5 -13 423 690 ;
+C -1 ; WX 500 ; N thorn ; B -120 -205 446 699 ;
+C -1 ; WX 444 ; N egrave ; B 5 -13 398 697 ;
+C -1 ; WX 300 ; N twosuperior ; B 2 274 313 683 ;
+C -1 ; WX 444 ; N eacute ; B 5 -13 435 697 ;
+C -1 ; WX 500 ; N otilde ; B -3 -13 491 655 ;
+C -1 ; WX 667 ; N Aacute ; B -67 0 593 904 ;
+C -1 ; WX 500 ; N ocircumflex ; B -3 -13 451 690 ;
+C -1 ; WX 444 ; N yacute ; B -94 -205 435 697 ;
+C -1 ; WX 556 ; N udieresis ; B 15 -9 494 655 ;
+C -1 ; WX 750 ; N threequarters ; B 7 -14 726 683 ;
+C -1 ; WX 500 ; N acircumflex ; B -21 -14 455 690 ;
+C -1 ; WX 722 ; N Eth ; B -31 0 700 669 ;
+C -1 ; WX 444 ; N edieresis ; B 5 -13 443 655 ;
+C -1 ; WX 556 ; N ugrave ; B 15 -9 492 697 ;
+C -1 ; WX 1000 ; N trademark ; B 32 263 968 669 ;
+C -1 ; WX 500 ; N ograve ; B -3 -13 441 697 ;
+C -1 ; WX 389 ; N scaron ; B -19 -13 439 690 ;
+C -1 ; WX 389 ; N Idieresis ; B -32 0 445 862 ;
+C -1 ; WX 556 ; N uacute ; B 15 -9 492 697 ;
+C -1 ; WX 500 ; N agrave ; B -21 -14 455 697 ;
+C -1 ; WX 556 ; N ntilde ; B -6 -9 504 655 ;
+C -1 ; WX 500 ; N aring ; B -21 -14 455 729 ;
+C -1 ; WX 389 ; N zcaron ; B -43 -78 424 690 ;
+C -1 ; WX 389 ; N Icircumflex ; B -32 0 420 897 ;
+C -1 ; WX 722 ; N Ntilde ; B -27 -15 748 862 ;
+C -1 ; WX 556 ; N ucircumflex ; B 15 -9 492 690 ;
+C -1 ; WX 667 ; N Ecircumflex ; B -27 0 653 897 ;
+C -1 ; WX 389 ; N Iacute ; B -32 0 412 904 ;
+C -1 ; WX 667 ; N Ccedilla ; B 32 -218 677 685 ;
+C -1 ; WX 722 ; N Odieresis ; B 27 -18 691 862 ;
+C -1 ; WX 556 ; N Scaron ; B 2 -18 526 897 ;
+C -1 ; WX 667 ; N Edieresis ; B -27 0 653 862 ;
+C -1 ; WX 389 ; N Igrave ; B -32 0 406 904 ;
+C -1 ; WX 500 ; N adieresis ; B -21 -14 471 655 ;
+C -1 ; WX 722 ; N Ograve ; B 27 -18 691 904 ;
+C -1 ; WX 667 ; N Egrave ; B -27 0 653 904 ;
+C -1 ; WX 611 ; N Ydieresis ; B 73 0 659 862 ;
+C -1 ; WX 747 ; N registered ; B 30 -18 718 685 ;
+C -1 ; WX 722 ; N Otilde ; B 27 -18 691 862 ;
+C -1 ; WX 750 ; N onequarter ; B 7 -14 721 683 ;
+C -1 ; WX 722 ; N Ugrave ; B 67 -18 744 904 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 67 -18 744 897 ;
+C -1 ; WX 611 ; N Thorn ; B -27 0 573 669 ;
+C -1 ; WX 570 ; N divide ; B 33 -29 537 535 ;
+C -1 ; WX 667 ; N Atilde ; B -67 0 593 862 ;
+C -1 ; WX 722 ; N Uacute ; B 67 -18 744 904 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 27 -18 691 897 ;
+C -1 ; WX 606 ; N logicalnot ; B 51 108 555 399 ;
+C -1 ; WX 667 ; N Aring ; B -67 0 593 921 ;
+C -1 ; WX 278 ; N idieresis ; B 2 -9 360 655 ;
+C -1 ; WX 278 ; N iacute ; B 2 -9 352 697 ;
+C -1 ; WX 500 ; N aacute ; B -21 -14 463 697 ;
+C -1 ; WX 570 ; N plusminus ; B 33 0 537 506 ;
+C -1 ; WX 570 ; N multiply ; B 48 16 522 490 ;
+C -1 ; WX 722 ; N Udieresis ; B 67 -18 744 862 ;
+C -1 ; WX 606 ; N minus ; B 51 209 555 297 ;
+C -1 ; WX 300 ; N onesuperior ; B 30 274 301 683 ;
+C -1 ; WX 667 ; N Eacute ; B -27 0 653 904 ;
+C -1 ; WX 667 ; N Acircumflex ; B -67 0 593 897 ;
+C -1 ; WX 747 ; N copyright ; B 30 -18 718 685 ;
+C -1 ; WX 667 ; N Agrave ; B -67 0 593 904 ;
+C -1 ; WX 500 ; N odieresis ; B -3 -13 466 655 ;
+C -1 ; WX 500 ; N oacute ; B -3 -13 463 697 ;
+C -1 ; WX 400 ; N degree ; B 83 397 369 683 ;
+C -1 ; WX 278 ; N igrave ; B 2 -9 260 697 ;
+C -1 ; WX 576 ; N mu ; B -60 -207 516 449 ;
+C -1 ; WX 722 ; N Oacute ; B 27 -18 691 904 ;
+C -1 ; WX 500 ; N eth ; B -3 -13 454 699 ;
+C -1 ; WX 667 ; N Adieresis ; B -67 0 593 862 ;
+C -1 ; WX 611 ; N Yacute ; B 73 0 659 904 ;
+C -1 ; WX 220 ; N brokenbar ; B 66 -18 154 685 ;
+C -1 ; WX 750 ; N onehalf ; B -9 -14 723 683 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 283
+
+KPX A y -74
+KPX A w -74
+KPX A v -74
+KPX A u -30
+KPX A quoteright -74
+KPX A quotedblright 0
+KPX A p 0
+KPX A Y -70
+KPX A W -100
+KPX A V -95
+KPX A U -50
+KPX A T -55
+KPX A Q -55
+KPX A O -50
+KPX A G -60
+KPX A C -65
+
+KPX B period 0
+KPX B comma 0
+KPX B U -10
+KPX B A -25
+
+KPX D period 0
+KPX D comma 0
+KPX D Y -50
+KPX D W -40
+KPX D V -50
+KPX D A -25
+
+KPX F r -50
+KPX F period -129
+KPX F o -70
+KPX F i -40
+KPX F e -100
+KPX F comma -129
+KPX F a -95
+KPX F A -100
+
+KPX G period 0
+KPX G comma 0
+
+KPX J u -40
+KPX J period -10
+KPX J o -40
+KPX J e -40
+KPX J comma -10
+KPX J a -40
+KPX J A -25
+
+KPX K y -20
+KPX K u -20
+KPX K o -25
+KPX K e -25
+KPX K O -30
+
+KPX L y -37
+KPX L quoteright -55
+KPX L quotedblright 0
+KPX L Y -37
+KPX L W -37
+KPX L V -37
+KPX L T -18
+
+KPX N period 0
+KPX N comma 0
+KPX N A -30
+
+KPX O period 0
+KPX O comma 0
+KPX O Y -50
+KPX O X -40
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -40
+
+KPX P period -129
+KPX P o -55
+KPX P e -50
+KPX P comma -129
+KPX P a -40
+KPX P A -85
+
+KPX Q period 0
+KPX Q comma 0
+KPX Q U -10
+
+KPX R Y -18
+KPX R W -18
+KPX R V -18
+KPX R U -40
+KPX R T -30
+KPX R O -40
+
+KPX S period 0
+KPX S comma 0
+
+KPX T y -37
+KPX T w -37
+KPX T u -37
+KPX T semicolon -74
+KPX T r -37
+KPX T period -92
+KPX T o -95
+KPX T i -37
+KPX T hyphen -92
+KPX T h 0
+KPX T e -92
+KPX T comma -92
+KPX T colon -74
+KPX T a -92
+KPX T O -18
+KPX T A -55
+
+KPX U period 0
+KPX U comma 0
+KPX U A -45
+
+KPX V u -55
+KPX V semicolon -74
+KPX V period -129
+KPX V o -111
+KPX V i -55
+KPX V hyphen -70
+KPX V e -111
+KPX V comma -129
+KPX V colon -74
+KPX V a -111
+KPX V O -30
+KPX V G -10
+KPX V A -85
+
+KPX W y -55
+KPX W u -55
+KPX W semicolon -55
+KPX W period -74
+KPX W o -80
+KPX W i -37
+KPX W hyphen -50
+KPX W h 0
+KPX W e -90
+KPX W comma -74
+KPX W colon -55
+KPX W a -85
+KPX W O -15
+KPX W A -74
+
+KPX Y u -92
+KPX Y semicolon -92
+KPX Y period -74
+KPX Y o -111
+KPX Y i -55
+KPX Y hyphen -92
+KPX Y e -111
+KPX Y comma -92
+KPX Y colon -92
+KPX Y a -92
+KPX Y O -25
+KPX Y A -74
+
+KPX a y 0
+KPX a w 0
+KPX a v 0
+KPX a t 0
+KPX a p 0
+KPX a g 0
+KPX a b 0
+
+KPX b y 0
+KPX b v 0
+KPX b u -20
+KPX b period -40
+KPX b l 0
+KPX b comma 0
+KPX b b -10
+
+KPX c y 0
+KPX c period 0
+KPX c l 0
+KPX c k -10
+KPX c h -10
+KPX c comma 0
+
+KPX colon space 0
+
+KPX comma space 0
+KPX comma quoteright -95
+KPX comma quotedblright -95
+
+KPX d y 0
+KPX d w 0
+KPX d v 0
+KPX d period 0
+KPX d d 0
+KPX d comma 0
+
+KPX e y 0
+KPX e x 0
+KPX e w 0
+KPX e v 0
+KPX e period 0
+KPX e p 0
+KPX e g 0
+KPX e comma 0
+KPX e b -10
+
+KPX f quoteright 55
+KPX f quotedblright 0
+KPX f period -10
+KPX f o -10
+KPX f l 0
+KPX f i 0
+KPX f f -18
+KPX f e -10
+KPX f dotlessi -30
+KPX f comma -10
+KPX f a 0
+
+KPX g y 0
+KPX g r 0
+KPX g period 0
+KPX g o 0
+KPX g i 0
+KPX g g 0
+KPX g e 0
+KPX g comma 0
+KPX g a 0
+
+KPX h y 0
+
+KPX i v 0
+
+KPX k y 0
+KPX k o -10
+KPX k e -30
+
+KPX l y 0
+KPX l w 0
+
+KPX m y 0
+KPX m u 0
+
+KPX n y 0
+KPX n v -40
+KPX n u 0
+
+KPX o y -10
+KPX o x -10
+KPX o w -25
+KPX o v -15
+KPX o g 0
+
+KPX p y 0
+
+KPX period quoteright -95
+KPX period quotedblright -95
+
+KPX quotedblleft quoteleft 0
+KPX quotedblleft A 0
+
+KPX quotedblright space 0
+
+KPX quoteleft quoteleft -74
+KPX quoteleft A 0
+
+KPX quoteright v -15
+KPX quoteright t -37
+KPX quoteright space -74
+KPX quoteright s -74
+KPX quoteright r -15
+KPX quoteright quoteright -74
+KPX quoteright quotedblright 0
+KPX quoteright l 0
+KPX quoteright d -15
+
+KPX r y 0
+KPX r v 0
+KPX r u 0
+KPX r t 0
+KPX r s 0
+KPX r r 0
+KPX r q 0
+KPX r period -65
+KPX r p 0
+KPX r o 0
+KPX r n 0
+KPX r m 0
+KPX r l 0
+KPX r k 0
+KPX r i 0
+KPX r hyphen 0
+KPX r g 0
+KPX r e 0
+KPX r d 0
+KPX r comma -65
+KPX r c 0
+KPX r a 0
+
+KPX s w 0
+
+KPX space quoteleft 0
+KPX space quotedblleft 0
+KPX space Y -70
+KPX space W -70
+KPX space V -70
+KPX space T 0
+KPX space A -37
+
+KPX v period -37
+KPX v o -15
+KPX v e -15
+KPX v comma -37
+KPX v a 0
+
+KPX w period -37
+KPX w o -15
+KPX w h 0
+KPX w e -10
+KPX w comma -37
+KPX w a -10
+
+KPX x e -10
+
+KPX y period -37
+KPX y o 0
+KPX y e 0
+KPX y comma -37
+KPX y a 0
+
+KPX z o 0
+KPX z e 0
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 172 207 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 187 207 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 167 207 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 172 207 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 157 192 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 167 207 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 172 207 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 187 207 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 187 207 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 172 207 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 33 207 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 53 207 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 48 207 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 33 207 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 210 207 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 200 207 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 230 207 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 215 207 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 200 207 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 207 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 207 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 210 207 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 230 207 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 230 207 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 200 207 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 154 207 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 169 207 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 207 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 74 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 74 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 84 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 46 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 46 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -42 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -37 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -37 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 97 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 69 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 74 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 112 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 112 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 97 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 102 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 41 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 13 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Times-Italic.afm b/tlt3.0/library/afm/Times-Italic.afm
new file mode 100644
index 0000000..1db2cff
--- /dev/null
+++ b/tlt3.0/library/afm/Times-Italic.afm
@@ -0,0 +1,649 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Mar 20 13:14:56 1990
+Comment UniqueID 28427
+Comment VMusage 32912 39804
+FontName Times-Italic
+FullName Times Italic
+FamilyName Times
+Weight Medium
+ItalicAngle -15.5
+IsFixedPitch false
+FontBBox -169 -217 1010 883
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 653
+XHeight 441
+Ascender 683
+Descender -205
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 39 -11 302 667 ;
+C 34 ; WX 420 ; N quotedbl ; B 144 421 432 666 ;
+C 35 ; WX 500 ; N numbersign ; B 2 0 540 676 ;
+C 36 ; WX 500 ; N dollar ; B 31 -89 497 731 ;
+C 37 ; WX 833 ; N percent ; B 79 -13 790 676 ;
+C 38 ; WX 778 ; N ampersand ; B 76 -18 723 666 ;
+C 39 ; WX 333 ; N quoteright ; B 151 436 290 666 ;
+C 40 ; WX 333 ; N parenleft ; B 42 -181 315 669 ;
+C 41 ; WX 333 ; N parenright ; B 16 -180 289 669 ;
+C 42 ; WX 500 ; N asterisk ; B 128 255 492 666 ;
+C 43 ; WX 675 ; N plus ; B 86 0 590 506 ;
+C 44 ; WX 250 ; N comma ; B -4 -129 135 101 ;
+C 45 ; WX 333 ; N hyphen ; B 49 192 282 255 ;
+C 46 ; WX 250 ; N period ; B 27 -11 138 100 ;
+C 47 ; WX 278 ; N slash ; B -65 -18 386 666 ;
+C 48 ; WX 500 ; N zero ; B 32 -7 497 676 ;
+C 49 ; WX 500 ; N one ; B 49 0 409 676 ;
+C 50 ; WX 500 ; N two ; B 12 0 452 676 ;
+C 51 ; WX 500 ; N three ; B 15 -7 465 676 ;
+C 52 ; WX 500 ; N four ; B 1 0 479 676 ;
+C 53 ; WX 500 ; N five ; B 15 -7 491 666 ;
+C 54 ; WX 500 ; N six ; B 30 -7 521 686 ;
+C 55 ; WX 500 ; N seven ; B 75 -8 537 666 ;
+C 56 ; WX 500 ; N eight ; B 30 -7 493 676 ;
+C 57 ; WX 500 ; N nine ; B 23 -17 492 676 ;
+C 58 ; WX 333 ; N colon ; B 50 -11 261 441 ;
+C 59 ; WX 333 ; N semicolon ; B 27 -129 261 441 ;
+C 60 ; WX 675 ; N less ; B 84 -8 592 514 ;
+C 61 ; WX 675 ; N equal ; B 86 120 590 386 ;
+C 62 ; WX 675 ; N greater ; B 84 -8 592 514 ;
+C 63 ; WX 500 ; N question ; B 132 -12 472 664 ;
+C 64 ; WX 920 ; N at ; B 118 -18 806 666 ;
+C 65 ; WX 611 ; N A ; B -51 0 564 668 ;
+C 66 ; WX 611 ; N B ; B -8 0 588 653 ;
+C 67 ; WX 667 ; N C ; B 66 -18 689 666 ;
+C 68 ; WX 722 ; N D ; B -8 0 700 653 ;
+C 69 ; WX 611 ; N E ; B -1 0 634 653 ;
+C 70 ; WX 611 ; N F ; B 8 0 645 653 ;
+C 71 ; WX 722 ; N G ; B 52 -18 722 666 ;
+C 72 ; WX 722 ; N H ; B -8 0 767 653 ;
+C 73 ; WX 333 ; N I ; B -8 0 384 653 ;
+C 74 ; WX 444 ; N J ; B -6 -18 491 653 ;
+C 75 ; WX 667 ; N K ; B 7 0 722 653 ;
+C 76 ; WX 556 ; N L ; B -8 0 559 653 ;
+C 77 ; WX 833 ; N M ; B -18 0 873 653 ;
+C 78 ; WX 667 ; N N ; B -20 -15 727 653 ;
+C 79 ; WX 722 ; N O ; B 60 -18 699 666 ;
+C 80 ; WX 611 ; N P ; B 0 0 605 653 ;
+C 81 ; WX 722 ; N Q ; B 59 -182 699 666 ;
+C 82 ; WX 611 ; N R ; B -13 0 588 653 ;
+C 83 ; WX 500 ; N S ; B 17 -18 508 667 ;
+C 84 ; WX 556 ; N T ; B 59 0 633 653 ;
+C 85 ; WX 722 ; N U ; B 102 -18 765 653 ;
+C 86 ; WX 611 ; N V ; B 76 -18 688 653 ;
+C 87 ; WX 833 ; N W ; B 71 -18 906 653 ;
+C 88 ; WX 611 ; N X ; B -29 0 655 653 ;
+C 89 ; WX 556 ; N Y ; B 78 0 633 653 ;
+C 90 ; WX 556 ; N Z ; B -6 0 606 653 ;
+C 91 ; WX 389 ; N bracketleft ; B 21 -153 391 663 ;
+C 92 ; WX 278 ; N backslash ; B -41 -18 319 666 ;
+C 93 ; WX 389 ; N bracketright ; B 12 -153 382 663 ;
+C 94 ; WX 422 ; N asciicircum ; B 0 301 422 666 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 171 436 310 666 ;
+C 97 ; WX 500 ; N a ; B 17 -11 476 441 ;
+C 98 ; WX 500 ; N b ; B 23 -11 473 683 ;
+C 99 ; WX 444 ; N c ; B 30 -11 425 441 ;
+C 100 ; WX 500 ; N d ; B 15 -13 527 683 ;
+C 101 ; WX 444 ; N e ; B 31 -11 412 441 ;
+C 102 ; WX 278 ; N f ; B -147 -207 424 678 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 8 -206 472 441 ;
+C 104 ; WX 500 ; N h ; B 19 -9 478 683 ;
+C 105 ; WX 278 ; N i ; B 49 -11 264 654 ;
+C 106 ; WX 278 ; N j ; B -124 -207 276 654 ;
+C 107 ; WX 444 ; N k ; B 14 -11 461 683 ;
+C 108 ; WX 278 ; N l ; B 41 -11 279 683 ;
+C 109 ; WX 722 ; N m ; B 12 -9 704 441 ;
+C 110 ; WX 500 ; N n ; B 14 -9 474 441 ;
+C 111 ; WX 500 ; N o ; B 27 -11 468 441 ;
+C 112 ; WX 500 ; N p ; B -75 -205 469 441 ;
+C 113 ; WX 500 ; N q ; B 25 -209 483 441 ;
+C 114 ; WX 389 ; N r ; B 45 0 412 441 ;
+C 115 ; WX 389 ; N s ; B 16 -13 366 442 ;
+C 116 ; WX 278 ; N t ; B 37 -11 296 546 ;
+C 117 ; WX 500 ; N u ; B 42 -11 475 441 ;
+C 118 ; WX 444 ; N v ; B 21 -18 426 441 ;
+C 119 ; WX 667 ; N w ; B 16 -18 648 441 ;
+C 120 ; WX 444 ; N x ; B -27 -11 447 441 ;
+C 121 ; WX 444 ; N y ; B -24 -206 426 441 ;
+C 122 ; WX 389 ; N z ; B -2 -81 380 428 ;
+C 123 ; WX 400 ; N braceleft ; B 51 -177 407 687 ;
+C 124 ; WX 275 ; N bar ; B 105 -18 171 666 ;
+C 125 ; WX 400 ; N braceright ; B -7 -177 349 687 ;
+C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
+C 161 ; WX 389 ; N exclamdown ; B 59 -205 322 473 ;
+C 162 ; WX 500 ; N cent ; B 77 -143 472 560 ;
+C 163 ; WX 500 ; N sterling ; B 10 -6 517 670 ;
+C 164 ; WX 167 ; N fraction ; B -169 -10 337 676 ;
+C 165 ; WX 500 ; N yen ; B 27 0 603 653 ;
+C 166 ; WX 500 ; N florin ; B 25 -182 507 682 ;
+C 167 ; WX 500 ; N section ; B 53 -162 461 666 ;
+C 168 ; WX 500 ; N currency ; B -22 53 522 597 ;
+C 169 ; WX 214 ; N quotesingle ; B 132 421 241 666 ;
+C 170 ; WX 556 ; N quotedblleft ; B 166 436 514 666 ;
+C 171 ; WX 500 ; N guillemotleft ; B 53 37 445 403 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 51 37 281 403 ;
+C 173 ; WX 333 ; N guilsinglright ; B 52 37 282 403 ;
+C 174 ; WX 500 ; N fi ; B -141 -207 481 681 ;
+C 175 ; WX 500 ; N fl ; B -141 -204 518 682 ;
+C 177 ; WX 500 ; N endash ; B -6 197 505 243 ;
+C 178 ; WX 500 ; N dagger ; B 101 -159 488 666 ;
+C 179 ; WX 500 ; N daggerdbl ; B 22 -143 491 666 ;
+C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
+C 182 ; WX 523 ; N paragraph ; B 55 -123 616 653 ;
+C 183 ; WX 350 ; N bullet ; B 40 191 310 461 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 44 -129 183 101 ;
+C 185 ; WX 556 ; N quotedblbase ; B 57 -129 405 101 ;
+C 186 ; WX 556 ; N quotedblright ; B 151 436 499 666 ;
+C 187 ; WX 500 ; N guillemotright ; B 55 37 447 403 ;
+C 188 ; WX 889 ; N ellipsis ; B 57 -11 762 100 ;
+C 189 ; WX 1000 ; N perthousand ; B 25 -19 1010 706 ;
+C 191 ; WX 500 ; N questiondown ; B 28 -205 368 471 ;
+C 193 ; WX 333 ; N grave ; B 121 492 311 664 ;
+C 194 ; WX 333 ; N acute ; B 180 494 403 664 ;
+C 195 ; WX 333 ; N circumflex ; B 91 492 385 661 ;
+C 196 ; WX 333 ; N tilde ; B 100 517 427 624 ;
+C 197 ; WX 333 ; N macron ; B 99 532 411 583 ;
+C 198 ; WX 333 ; N breve ; B 117 492 418 650 ;
+C 199 ; WX 333 ; N dotaccent ; B 207 508 305 606 ;
+C 200 ; WX 333 ; N dieresis ; B 107 508 405 606 ;
+C 202 ; WX 333 ; N ring ; B 155 492 355 691 ;
+C 203 ; WX 333 ; N cedilla ; B -30 -217 182 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B 93 494 486 664 ;
+C 206 ; WX 333 ; N ogonek ; B -20 -169 200 40 ;
+C 207 ; WX 333 ; N caron ; B 121 492 426 661 ;
+C 208 ; WX 889 ; N emdash ; B -6 197 894 243 ;
+C 225 ; WX 889 ; N AE ; B -27 0 911 653 ;
+C 227 ; WX 276 ; N ordfeminine ; B 42 406 352 676 ;
+C 232 ; WX 556 ; N Lslash ; B -8 0 559 653 ;
+C 233 ; WX 722 ; N Oslash ; B 60 -105 699 722 ;
+C 234 ; WX 944 ; N OE ; B 49 -8 964 666 ;
+C 235 ; WX 310 ; N ordmasculine ; B 67 406 362 676 ;
+C 241 ; WX 667 ; N ae ; B 23 -11 640 441 ;
+C 245 ; WX 278 ; N dotlessi ; B 49 -11 235 441 ;
+C 248 ; WX 278 ; N lslash ; B 37 -11 307 683 ;
+C 249 ; WX 500 ; N oslash ; B 28 -135 469 554 ;
+C 250 ; WX 667 ; N oe ; B 20 -12 646 441 ;
+C 251 ; WX 500 ; N germandbls ; B -168 -207 493 679 ;
+C -1 ; WX 556 ; N Zcaron ; B -6 0 606 873 ;
+C -1 ; WX 444 ; N ccedilla ; B 26 -217 425 441 ;
+C -1 ; WX 444 ; N ydieresis ; B -24 -206 441 606 ;
+C -1 ; WX 500 ; N atilde ; B 17 -11 511 624 ;
+C -1 ; WX 278 ; N icircumflex ; B 34 -11 328 661 ;
+C -1 ; WX 300 ; N threesuperior ; B 43 268 339 676 ;
+C -1 ; WX 444 ; N ecircumflex ; B 31 -11 441 661 ;
+C -1 ; WX 500 ; N thorn ; B -75 -205 469 683 ;
+C -1 ; WX 444 ; N egrave ; B 31 -11 412 664 ;
+C -1 ; WX 300 ; N twosuperior ; B 33 271 324 676 ;
+C -1 ; WX 444 ; N eacute ; B 31 -11 459 664 ;
+C -1 ; WX 500 ; N otilde ; B 27 -11 496 624 ;
+C -1 ; WX 611 ; N Aacute ; B -51 0 564 876 ;
+C -1 ; WX 500 ; N ocircumflex ; B 27 -11 468 661 ;
+C -1 ; WX 444 ; N yacute ; B -24 -206 459 664 ;
+C -1 ; WX 500 ; N udieresis ; B 42 -11 479 606 ;
+C -1 ; WX 750 ; N threequarters ; B 23 -10 736 676 ;
+C -1 ; WX 500 ; N acircumflex ; B 17 -11 476 661 ;
+C -1 ; WX 722 ; N Eth ; B -8 0 700 653 ;
+C -1 ; WX 444 ; N edieresis ; B 31 -11 451 606 ;
+C -1 ; WX 500 ; N ugrave ; B 42 -11 475 664 ;
+C -1 ; WX 980 ; N trademark ; B 30 247 957 653 ;
+C -1 ; WX 500 ; N ograve ; B 27 -11 468 664 ;
+C -1 ; WX 389 ; N scaron ; B 16 -13 454 661 ;
+C -1 ; WX 333 ; N Idieresis ; B -8 0 435 818 ;
+C -1 ; WX 500 ; N uacute ; B 42 -11 477 664 ;
+C -1 ; WX 500 ; N agrave ; B 17 -11 476 664 ;
+C -1 ; WX 500 ; N ntilde ; B 14 -9 476 624 ;
+C -1 ; WX 500 ; N aring ; B 17 -11 476 691 ;
+C -1 ; WX 389 ; N zcaron ; B -2 -81 434 661 ;
+C -1 ; WX 333 ; N Icircumflex ; B -8 0 425 873 ;
+C -1 ; WX 667 ; N Ntilde ; B -20 -15 727 836 ;
+C -1 ; WX 500 ; N ucircumflex ; B 42 -11 475 661 ;
+C -1 ; WX 611 ; N Ecircumflex ; B -1 0 634 873 ;
+C -1 ; WX 333 ; N Iacute ; B -8 0 413 876 ;
+C -1 ; WX 667 ; N Ccedilla ; B 66 -217 689 666 ;
+C -1 ; WX 722 ; N Odieresis ; B 60 -18 699 818 ;
+C -1 ; WX 500 ; N Scaron ; B 17 -18 520 873 ;
+C -1 ; WX 611 ; N Edieresis ; B -1 0 634 818 ;
+C -1 ; WX 333 ; N Igrave ; B -8 0 384 876 ;
+C -1 ; WX 500 ; N adieresis ; B 17 -11 489 606 ;
+C -1 ; WX 722 ; N Ograve ; B 60 -18 699 876 ;
+C -1 ; WX 611 ; N Egrave ; B -1 0 634 876 ;
+C -1 ; WX 556 ; N Ydieresis ; B 78 0 633 818 ;
+C -1 ; WX 760 ; N registered ; B 41 -18 719 666 ;
+C -1 ; WX 722 ; N Otilde ; B 60 -18 699 836 ;
+C -1 ; WX 750 ; N onequarter ; B 33 -10 736 676 ;
+C -1 ; WX 722 ; N Ugrave ; B 102 -18 765 876 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 102 -18 765 873 ;
+C -1 ; WX 611 ; N Thorn ; B 0 0 569 653 ;
+C -1 ; WX 675 ; N divide ; B 86 -11 590 517 ;
+C -1 ; WX 611 ; N Atilde ; B -51 0 566 836 ;
+C -1 ; WX 722 ; N Uacute ; B 102 -18 765 876 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 60 -18 699 873 ;
+C -1 ; WX 675 ; N logicalnot ; B 86 108 590 386 ;
+C -1 ; WX 611 ; N Aring ; B -51 0 564 883 ;
+C -1 ; WX 278 ; N idieresis ; B 49 -11 353 606 ;
+C -1 ; WX 278 ; N iacute ; B 49 -11 356 664 ;
+C -1 ; WX 500 ; N aacute ; B 17 -11 487 664 ;
+C -1 ; WX 675 ; N plusminus ; B 86 0 590 506 ;
+C -1 ; WX 675 ; N multiply ; B 93 8 582 497 ;
+C -1 ; WX 722 ; N Udieresis ; B 102 -18 765 818 ;
+C -1 ; WX 675 ; N minus ; B 86 220 590 286 ;
+C -1 ; WX 300 ; N onesuperior ; B 43 271 284 676 ;
+C -1 ; WX 611 ; N Eacute ; B -1 0 634 876 ;
+C -1 ; WX 611 ; N Acircumflex ; B -51 0 564 873 ;
+C -1 ; WX 760 ; N copyright ; B 41 -18 719 666 ;
+C -1 ; WX 611 ; N Agrave ; B -51 0 564 876 ;
+C -1 ; WX 500 ; N odieresis ; B 27 -11 489 606 ;
+C -1 ; WX 500 ; N oacute ; B 27 -11 487 664 ;
+C -1 ; WX 400 ; N degree ; B 101 390 387 676 ;
+C -1 ; WX 278 ; N igrave ; B 49 -11 284 664 ;
+C -1 ; WX 500 ; N mu ; B -30 -209 497 428 ;
+C -1 ; WX 722 ; N Oacute ; B 60 -18 699 876 ;
+C -1 ; WX 500 ; N eth ; B 27 -11 482 683 ;
+C -1 ; WX 611 ; N Adieresis ; B -51 0 564 818 ;
+C -1 ; WX 556 ; N Yacute ; B 78 0 633 876 ;
+C -1 ; WX 275 ; N brokenbar ; B 105 -18 171 666 ;
+C -1 ; WX 750 ; N onehalf ; B 34 -10 749 676 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 283
+
+KPX A y -55
+KPX A w -55
+KPX A v -55
+KPX A u -20
+KPX A quoteright -37
+KPX A quotedblright 0
+KPX A p 0
+KPX A Y -55
+KPX A W -95
+KPX A V -105
+KPX A U -50
+KPX A T -37
+KPX A Q -40
+KPX A O -40
+KPX A G -35
+KPX A C -30
+
+KPX B period 0
+KPX B comma 0
+KPX B U -10
+KPX B A -25
+
+KPX D period 0
+KPX D comma 0
+KPX D Y -40
+KPX D W -40
+KPX D V -40
+KPX D A -35
+
+KPX F r -55
+KPX F period -135
+KPX F o -105
+KPX F i -45
+KPX F e -75
+KPX F comma -135
+KPX F a -75
+KPX F A -115
+
+KPX G period 0
+KPX G comma 0
+
+KPX J u -35
+KPX J period -25
+KPX J o -25
+KPX J e -25
+KPX J comma -25
+KPX J a -35
+KPX J A -40
+
+KPX K y -40
+KPX K u -40
+KPX K o -40
+KPX K e -35
+KPX K O -50
+
+KPX L y -30
+KPX L quoteright -37
+KPX L quotedblright 0
+KPX L Y -20
+KPX L W -55
+KPX L V -55
+KPX L T -20
+
+KPX N period 0
+KPX N comma 0
+KPX N A -27
+
+KPX O period 0
+KPX O comma 0
+KPX O Y -50
+KPX O X -40
+KPX O W -50
+KPX O V -50
+KPX O T -40
+KPX O A -55
+
+KPX P period -135
+KPX P o -80
+KPX P e -80
+KPX P comma -135
+KPX P a -80
+KPX P A -90
+
+KPX Q period 0
+KPX Q comma 0
+KPX Q U -10
+
+KPX R Y -18
+KPX R W -18
+KPX R V -18
+KPX R U -40
+KPX R T 0
+KPX R O -40
+
+KPX S period 0
+KPX S comma 0
+
+KPX T y -74
+KPX T w -74
+KPX T u -55
+KPX T semicolon -65
+KPX T r -55
+KPX T period -74
+KPX T o -92
+KPX T i -55
+KPX T hyphen -74
+KPX T h 0
+KPX T e -92
+KPX T comma -74
+KPX T colon -55
+KPX T a -92
+KPX T O -18
+KPX T A -50
+
+KPX U period -25
+KPX U comma -25
+KPX U A -40
+
+KPX V u -74
+KPX V semicolon -74
+KPX V period -129
+KPX V o -111
+KPX V i -74
+KPX V hyphen -55
+KPX V e -111
+KPX V comma -129
+KPX V colon -65
+KPX V a -111
+KPX V O -30
+KPX V G 0
+KPX V A -60
+
+KPX W y -70
+KPX W u -55
+KPX W semicolon -65
+KPX W period -92
+KPX W o -92
+KPX W i -55
+KPX W hyphen -37
+KPX W h 0
+KPX W e -92
+KPX W comma -92
+KPX W colon -65
+KPX W a -92
+KPX W O -25
+KPX W A -60
+
+KPX Y u -92
+KPX Y semicolon -65
+KPX Y period -92
+KPX Y o -92
+KPX Y i -74
+KPX Y hyphen -74
+KPX Y e -92
+KPX Y comma -92
+KPX Y colon -65
+KPX Y a -92
+KPX Y O -15
+KPX Y A -50
+
+KPX a y 0
+KPX a w 0
+KPX a v 0
+KPX a t 0
+KPX a p 0
+KPX a g -10
+KPX a b 0
+
+KPX b y 0
+KPX b v 0
+KPX b u -20
+KPX b period -40
+KPX b l 0
+KPX b comma 0
+KPX b b 0
+
+KPX c y 0
+KPX c period 0
+KPX c l 0
+KPX c k -20
+KPX c h -15
+KPX c comma 0
+
+KPX colon space 0
+
+KPX comma space 0
+KPX comma quoteright -140
+KPX comma quotedblright -140
+
+KPX d y 0
+KPX d w 0
+KPX d v 0
+KPX d period 0
+KPX d d 0
+KPX d comma 0
+
+KPX e y -30
+KPX e x -20
+KPX e w -15
+KPX e v -15
+KPX e period -15
+KPX e p 0
+KPX e g -40
+KPX e comma -10
+KPX e b 0
+
+KPX f quoteright 92
+KPX f quotedblright 0
+KPX f period -15
+KPX f o 0
+KPX f l 0
+KPX f i -20
+KPX f f -18
+KPX f e 0
+KPX f dotlessi -60
+KPX f comma -10
+KPX f a 0
+
+KPX g y 0
+KPX g r 0
+KPX g period -15
+KPX g o 0
+KPX g i 0
+KPX g g -10
+KPX g e -10
+KPX g comma -10
+KPX g a 0
+
+KPX h y 0
+
+KPX i v 0
+
+KPX k y -10
+KPX k o -10
+KPX k e -10
+
+KPX l y 0
+KPX l w 0
+
+KPX m y 0
+KPX m u 0
+
+KPX n y 0
+KPX n v -40
+KPX n u 0
+
+KPX o y 0
+KPX o x 0
+KPX o w 0
+KPX o v -10
+KPX o g -10
+
+KPX p y 0
+
+KPX period quoteright -140
+KPX period quotedblright -140
+
+KPX quotedblleft quoteleft 0
+KPX quotedblleft A 0
+
+KPX quotedblright space 0
+
+KPX quoteleft quoteleft -111
+KPX quoteleft A 0
+
+KPX quoteright v -10
+KPX quoteright t -30
+KPX quoteright space -111
+KPX quoteright s -40
+KPX quoteright r -25
+KPX quoteright quoteright -111
+KPX quoteright quotedblright 0
+KPX quoteright l 0
+KPX quoteright d -25
+
+KPX r y 0
+KPX r v 0
+KPX r u 0
+KPX r t 0
+KPX r s -10
+KPX r r 0
+KPX r q -37
+KPX r period -111
+KPX r p 0
+KPX r o -45
+KPX r n 0
+KPX r m 0
+KPX r l 0
+KPX r k 0
+KPX r i 0
+KPX r hyphen -20
+KPX r g -37
+KPX r e -37
+KPX r d -37
+KPX r comma -111
+KPX r c -37
+KPX r a -15
+
+KPX s w 0
+
+KPX space quoteleft 0
+KPX space quotedblleft 0
+KPX space Y -75
+KPX space W -40
+KPX space V -35
+KPX space T -18
+KPX space A -18
+
+KPX v period -74
+KPX v o 0
+KPX v e 0
+KPX v comma -74
+KPX v a 0
+
+KPX w period -74
+KPX w o 0
+KPX w h 0
+KPX w e 0
+KPX w comma -74
+KPX w a 0
+
+KPX x e 0
+
+KPX y period -55
+KPX y o 0
+KPX y e 0
+KPX y comma -55
+KPX y a 0
+
+KPX z o 0
+KPX z e 0
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 139 212 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 144 212 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 139 212 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 149 212 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 129 192 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 139 212 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 149 212 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 169 212 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 159 212 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 149 212 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 10 212 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 40 212 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 30 212 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 10 212 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 177 212 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 195 212 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 230 212 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 230 212 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 205 212 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 215 212 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 94 212 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 212 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 215 212 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 225 212 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 215 212 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 132 212 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 142 212 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 112 212 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 84 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 84 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 84 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 84 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 84 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 84 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 46 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -47 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -57 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -52 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 49 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 74 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 69 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 74 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 74 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 74 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 56 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 36 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 8 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/Times-Roman.afm b/tlt3.0/library/afm/Times-Roman.afm
new file mode 100644
index 0000000..58de46e
--- /dev/null
+++ b/tlt3.0/library/afm/Times-Roman.afm
@@ -0,0 +1,649 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Tue Mar 20 12:15:44 1990
+Comment UniqueID 28416
+Comment VMusage 30487 37379
+FontName Times-Roman
+FullName Times Roman
+FamilyName Times
+Weight Roman
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -168 -218 1000 898
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.Times is a trademark of Linotype AG and/or its subsidiaries.
+EncodingScheme AdobeStandardEncoding
+CapHeight 662
+XHeight 450
+Ascender 683
+Descender -217
+StartCharMetrics 228
+C 32 ; WX 250 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 333 ; N exclam ; B 130 -9 238 676 ;
+C 34 ; WX 408 ; N quotedbl ; B 77 431 331 676 ;
+C 35 ; WX 500 ; N numbersign ; B 5 0 496 662 ;
+C 36 ; WX 500 ; N dollar ; B 44 -87 457 727 ;
+C 37 ; WX 833 ; N percent ; B 61 -13 772 676 ;
+C 38 ; WX 778 ; N ampersand ; B 42 -13 750 676 ;
+C 39 ; WX 333 ; N quoteright ; B 79 433 218 676 ;
+C 40 ; WX 333 ; N parenleft ; B 48 -177 304 676 ;
+C 41 ; WX 333 ; N parenright ; B 29 -177 285 676 ;
+C 42 ; WX 500 ; N asterisk ; B 69 265 432 676 ;
+C 43 ; WX 564 ; N plus ; B 30 0 534 506 ;
+C 44 ; WX 250 ; N comma ; B 56 -141 195 102 ;
+C 45 ; WX 333 ; N hyphen ; B 39 194 285 257 ;
+C 46 ; WX 250 ; N period ; B 70 -11 181 100 ;
+C 47 ; WX 278 ; N slash ; B -9 -14 287 676 ;
+C 48 ; WX 500 ; N zero ; B 24 -14 476 676 ;
+C 49 ; WX 500 ; N one ; B 111 0 394 676 ;
+C 50 ; WX 500 ; N two ; B 30 0 475 676 ;
+C 51 ; WX 500 ; N three ; B 43 -14 431 676 ;
+C 52 ; WX 500 ; N four ; B 12 0 472 676 ;
+C 53 ; WX 500 ; N five ; B 32 -14 438 688 ;
+C 54 ; WX 500 ; N six ; B 34 -14 468 684 ;
+C 55 ; WX 500 ; N seven ; B 20 -8 449 662 ;
+C 56 ; WX 500 ; N eight ; B 56 -14 445 676 ;
+C 57 ; WX 500 ; N nine ; B 30 -22 459 676 ;
+C 58 ; WX 278 ; N colon ; B 81 -11 192 459 ;
+C 59 ; WX 278 ; N semicolon ; B 80 -141 219 459 ;
+C 60 ; WX 564 ; N less ; B 28 -8 536 514 ;
+C 61 ; WX 564 ; N equal ; B 30 120 534 386 ;
+C 62 ; WX 564 ; N greater ; B 28 -8 536 514 ;
+C 63 ; WX 444 ; N question ; B 68 -8 414 676 ;
+C 64 ; WX 921 ; N at ; B 116 -14 809 676 ;
+C 65 ; WX 722 ; N A ; B 15 0 706 674 ;
+C 66 ; WX 667 ; N B ; B 17 0 593 662 ;
+C 67 ; WX 667 ; N C ; B 28 -14 633 676 ;
+C 68 ; WX 722 ; N D ; B 16 0 685 662 ;
+C 69 ; WX 611 ; N E ; B 12 0 597 662 ;
+C 70 ; WX 556 ; N F ; B 12 0 546 662 ;
+C 71 ; WX 722 ; N G ; B 32 -14 709 676 ;
+C 72 ; WX 722 ; N H ; B 19 0 702 662 ;
+C 73 ; WX 333 ; N I ; B 18 0 315 662 ;
+C 74 ; WX 389 ; N J ; B 10 -14 370 662 ;
+C 75 ; WX 722 ; N K ; B 34 0 723 662 ;
+C 76 ; WX 611 ; N L ; B 12 0 598 662 ;
+C 77 ; WX 889 ; N M ; B 12 0 863 662 ;
+C 78 ; WX 722 ; N N ; B 12 -11 707 662 ;
+C 79 ; WX 722 ; N O ; B 34 -14 688 676 ;
+C 80 ; WX 556 ; N P ; B 16 0 542 662 ;
+C 81 ; WX 722 ; N Q ; B 34 -178 701 676 ;
+C 82 ; WX 667 ; N R ; B 17 0 659 662 ;
+C 83 ; WX 556 ; N S ; B 42 -14 491 676 ;
+C 84 ; WX 611 ; N T ; B 17 0 593 662 ;
+C 85 ; WX 722 ; N U ; B 14 -14 705 662 ;
+C 86 ; WX 722 ; N V ; B 16 -11 697 662 ;
+C 87 ; WX 944 ; N W ; B 5 -11 932 662 ;
+C 88 ; WX 722 ; N X ; B 10 0 704 662 ;
+C 89 ; WX 722 ; N Y ; B 22 0 703 662 ;
+C 90 ; WX 611 ; N Z ; B 9 0 597 662 ;
+C 91 ; WX 333 ; N bracketleft ; B 88 -156 299 662 ;
+C 92 ; WX 278 ; N backslash ; B -9 -14 287 676 ;
+C 93 ; WX 333 ; N bracketright ; B 34 -156 245 662 ;
+C 94 ; WX 469 ; N asciicircum ; B 24 297 446 662 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 333 ; N quoteleft ; B 115 433 254 676 ;
+C 97 ; WX 444 ; N a ; B 37 -10 442 460 ;
+C 98 ; WX 500 ; N b ; B 3 -10 468 683 ;
+C 99 ; WX 444 ; N c ; B 25 -10 412 460 ;
+C 100 ; WX 500 ; N d ; B 27 -10 491 683 ;
+C 101 ; WX 444 ; N e ; B 25 -10 424 460 ;
+C 102 ; WX 333 ; N f ; B 20 0 383 683 ; L i fi ; L l fl ;
+C 103 ; WX 500 ; N g ; B 28 -218 470 460 ;
+C 104 ; WX 500 ; N h ; B 9 0 487 683 ;
+C 105 ; WX 278 ; N i ; B 16 0 253 683 ;
+C 106 ; WX 278 ; N j ; B -70 -218 194 683 ;
+C 107 ; WX 500 ; N k ; B 7 0 505 683 ;
+C 108 ; WX 278 ; N l ; B 19 0 257 683 ;
+C 109 ; WX 778 ; N m ; B 16 0 775 460 ;
+C 110 ; WX 500 ; N n ; B 16 0 485 460 ;
+C 111 ; WX 500 ; N o ; B 29 -10 470 460 ;
+C 112 ; WX 500 ; N p ; B 5 -217 470 460 ;
+C 113 ; WX 500 ; N q ; B 24 -217 488 460 ;
+C 114 ; WX 333 ; N r ; B 5 0 335 460 ;
+C 115 ; WX 389 ; N s ; B 51 -10 348 460 ;
+C 116 ; WX 278 ; N t ; B 13 -10 279 579 ;
+C 117 ; WX 500 ; N u ; B 9 -10 479 450 ;
+C 118 ; WX 500 ; N v ; B 19 -14 477 450 ;
+C 119 ; WX 722 ; N w ; B 21 -14 694 450 ;
+C 120 ; WX 500 ; N x ; B 17 0 479 450 ;
+C 121 ; WX 500 ; N y ; B 14 -218 475 450 ;
+C 122 ; WX 444 ; N z ; B 27 0 418 450 ;
+C 123 ; WX 480 ; N braceleft ; B 100 -181 350 680 ;
+C 124 ; WX 200 ; N bar ; B 67 -14 133 676 ;
+C 125 ; WX 480 ; N braceright ; B 130 -181 380 680 ;
+C 126 ; WX 541 ; N asciitilde ; B 40 183 502 323 ;
+C 161 ; WX 333 ; N exclamdown ; B 97 -218 205 467 ;
+C 162 ; WX 500 ; N cent ; B 53 -138 448 579 ;
+C 163 ; WX 500 ; N sterling ; B 12 -8 490 676 ;
+C 164 ; WX 167 ; N fraction ; B -168 -14 331 676 ;
+C 165 ; WX 500 ; N yen ; B -53 0 512 662 ;
+C 166 ; WX 500 ; N florin ; B 7 -189 490 676 ;
+C 167 ; WX 500 ; N section ; B 70 -148 426 676 ;
+C 168 ; WX 500 ; N currency ; B -22 58 522 602 ;
+C 169 ; WX 180 ; N quotesingle ; B 48 431 133 676 ;
+C 170 ; WX 444 ; N quotedblleft ; B 43 433 414 676 ;
+C 171 ; WX 500 ; N guillemotleft ; B 42 33 456 416 ;
+C 172 ; WX 333 ; N guilsinglleft ; B 63 33 285 416 ;
+C 173 ; WX 333 ; N guilsinglright ; B 48 33 270 416 ;
+C 174 ; WX 556 ; N fi ; B 31 0 521 683 ;
+C 175 ; WX 556 ; N fl ; B 32 0 521 683 ;
+C 177 ; WX 500 ; N endash ; B 0 201 500 250 ;
+C 178 ; WX 500 ; N dagger ; B 59 -149 442 676 ;
+C 179 ; WX 500 ; N daggerdbl ; B 58 -153 442 676 ;
+C 180 ; WX 250 ; N periodcentered ; B 70 199 181 310 ;
+C 182 ; WX 453 ; N paragraph ; B -22 -154 450 662 ;
+C 183 ; WX 350 ; N bullet ; B 40 196 310 466 ;
+C 184 ; WX 333 ; N quotesinglbase ; B 79 -141 218 102 ;
+C 185 ; WX 444 ; N quotedblbase ; B 45 -141 416 102 ;
+C 186 ; WX 444 ; N quotedblright ; B 30 433 401 676 ;
+C 187 ; WX 500 ; N guillemotright ; B 44 33 458 416 ;
+C 188 ; WX 1000 ; N ellipsis ; B 111 -11 888 100 ;
+C 189 ; WX 1000 ; N perthousand ; B 7 -19 994 706 ;
+C 191 ; WX 444 ; N questiondown ; B 30 -218 376 466 ;
+C 193 ; WX 333 ; N grave ; B 19 507 242 678 ;
+C 194 ; WX 333 ; N acute ; B 93 507 317 678 ;
+C 195 ; WX 333 ; N circumflex ; B 11 507 322 674 ;
+C 196 ; WX 333 ; N tilde ; B 1 532 331 638 ;
+C 197 ; WX 333 ; N macron ; B 11 547 322 601 ;
+C 198 ; WX 333 ; N breve ; B 26 507 307 664 ;
+C 199 ; WX 333 ; N dotaccent ; B 118 523 216 623 ;
+C 200 ; WX 333 ; N dieresis ; B 18 523 315 623 ;
+C 202 ; WX 333 ; N ring ; B 67 512 266 711 ;
+C 203 ; WX 333 ; N cedilla ; B 52 -215 261 0 ;
+C 205 ; WX 333 ; N hungarumlaut ; B -3 507 377 678 ;
+C 206 ; WX 333 ; N ogonek ; B 64 -165 249 0 ;
+C 207 ; WX 333 ; N caron ; B 11 507 322 674 ;
+C 208 ; WX 1000 ; N emdash ; B 0 201 1000 250 ;
+C 225 ; WX 889 ; N AE ; B 0 0 863 662 ;
+C 227 ; WX 276 ; N ordfeminine ; B 4 394 270 676 ;
+C 232 ; WX 611 ; N Lslash ; B 12 0 598 662 ;
+C 233 ; WX 722 ; N Oslash ; B 34 -80 688 734 ;
+C 234 ; WX 889 ; N OE ; B 30 -6 885 668 ;
+C 235 ; WX 310 ; N ordmasculine ; B 6 394 304 676 ;
+C 241 ; WX 667 ; N ae ; B 38 -10 632 460 ;
+C 245 ; WX 278 ; N dotlessi ; B 16 0 253 460 ;
+C 248 ; WX 278 ; N lslash ; B 19 0 259 683 ;
+C 249 ; WX 500 ; N oslash ; B 29 -112 470 551 ;
+C 250 ; WX 722 ; N oe ; B 30 -10 690 460 ;
+C 251 ; WX 500 ; N germandbls ; B 12 -9 468 683 ;
+C -1 ; WX 611 ; N Zcaron ; B 9 0 597 886 ;
+C -1 ; WX 444 ; N ccedilla ; B 25 -215 412 460 ;
+C -1 ; WX 500 ; N ydieresis ; B 14 -218 475 623 ;
+C -1 ; WX 444 ; N atilde ; B 37 -10 442 638 ;
+C -1 ; WX 278 ; N icircumflex ; B -16 0 295 674 ;
+C -1 ; WX 300 ; N threesuperior ; B 15 262 291 676 ;
+C -1 ; WX 444 ; N ecircumflex ; B 25 -10 424 674 ;
+C -1 ; WX 500 ; N thorn ; B 5 -217 470 683 ;
+C -1 ; WX 444 ; N egrave ; B 25 -10 424 678 ;
+C -1 ; WX 300 ; N twosuperior ; B 1 270 296 676 ;
+C -1 ; WX 444 ; N eacute ; B 25 -10 424 678 ;
+C -1 ; WX 500 ; N otilde ; B 29 -10 470 638 ;
+C -1 ; WX 722 ; N Aacute ; B 15 0 706 890 ;
+C -1 ; WX 500 ; N ocircumflex ; B 29 -10 470 674 ;
+C -1 ; WX 500 ; N yacute ; B 14 -218 475 678 ;
+C -1 ; WX 500 ; N udieresis ; B 9 -10 479 623 ;
+C -1 ; WX 750 ; N threequarters ; B 15 -14 718 676 ;
+C -1 ; WX 444 ; N acircumflex ; B 37 -10 442 674 ;
+C -1 ; WX 722 ; N Eth ; B 16 0 685 662 ;
+C -1 ; WX 444 ; N edieresis ; B 25 -10 424 623 ;
+C -1 ; WX 500 ; N ugrave ; B 9 -10 479 678 ;
+C -1 ; WX 980 ; N trademark ; B 30 256 957 662 ;
+C -1 ; WX 500 ; N ograve ; B 29 -10 470 678 ;
+C -1 ; WX 389 ; N scaron ; B 39 -10 350 674 ;
+C -1 ; WX 333 ; N Idieresis ; B 18 0 315 835 ;
+C -1 ; WX 500 ; N uacute ; B 9 -10 479 678 ;
+C -1 ; WX 444 ; N agrave ; B 37 -10 442 678 ;
+C -1 ; WX 500 ; N ntilde ; B 16 0 485 638 ;
+C -1 ; WX 444 ; N aring ; B 37 -10 442 711 ;
+C -1 ; WX 444 ; N zcaron ; B 27 0 418 674 ;
+C -1 ; WX 333 ; N Icircumflex ; B 11 0 322 886 ;
+C -1 ; WX 722 ; N Ntilde ; B 12 -11 707 850 ;
+C -1 ; WX 500 ; N ucircumflex ; B 9 -10 479 674 ;
+C -1 ; WX 611 ; N Ecircumflex ; B 12 0 597 886 ;
+C -1 ; WX 333 ; N Iacute ; B 18 0 317 890 ;
+C -1 ; WX 667 ; N Ccedilla ; B 28 -215 633 676 ;
+C -1 ; WX 722 ; N Odieresis ; B 34 -14 688 835 ;
+C -1 ; WX 556 ; N Scaron ; B 42 -14 491 886 ;
+C -1 ; WX 611 ; N Edieresis ; B 12 0 597 835 ;
+C -1 ; WX 333 ; N Igrave ; B 18 0 315 890 ;
+C -1 ; WX 444 ; N adieresis ; B 37 -10 442 623 ;
+C -1 ; WX 722 ; N Ograve ; B 34 -14 688 890 ;
+C -1 ; WX 611 ; N Egrave ; B 12 0 597 890 ;
+C -1 ; WX 722 ; N Ydieresis ; B 22 0 703 835 ;
+C -1 ; WX 760 ; N registered ; B 38 -14 722 676 ;
+C -1 ; WX 722 ; N Otilde ; B 34 -14 688 850 ;
+C -1 ; WX 750 ; N onequarter ; B 37 -14 718 676 ;
+C -1 ; WX 722 ; N Ugrave ; B 14 -14 705 890 ;
+C -1 ; WX 722 ; N Ucircumflex ; B 14 -14 705 886 ;
+C -1 ; WX 556 ; N Thorn ; B 16 0 542 662 ;
+C -1 ; WX 564 ; N divide ; B 30 -10 534 516 ;
+C -1 ; WX 722 ; N Atilde ; B 15 0 706 850 ;
+C -1 ; WX 722 ; N Uacute ; B 14 -14 705 890 ;
+C -1 ; WX 722 ; N Ocircumflex ; B 34 -14 688 886 ;
+C -1 ; WX 564 ; N logicalnot ; B 30 108 534 386 ;
+C -1 ; WX 722 ; N Aring ; B 15 0 706 898 ;
+C -1 ; WX 278 ; N idieresis ; B -9 0 288 623 ;
+C -1 ; WX 278 ; N iacute ; B 16 0 290 678 ;
+C -1 ; WX 444 ; N aacute ; B 37 -10 442 678 ;
+C -1 ; WX 564 ; N plusminus ; B 30 0 534 506 ;
+C -1 ; WX 564 ; N multiply ; B 38 8 527 497 ;
+C -1 ; WX 722 ; N Udieresis ; B 14 -14 705 835 ;
+C -1 ; WX 564 ; N minus ; B 30 220 534 286 ;
+C -1 ; WX 300 ; N onesuperior ; B 57 270 248 676 ;
+C -1 ; WX 611 ; N Eacute ; B 12 0 597 890 ;
+C -1 ; WX 722 ; N Acircumflex ; B 15 0 706 886 ;
+C -1 ; WX 760 ; N copyright ; B 38 -14 722 676 ;
+C -1 ; WX 722 ; N Agrave ; B 15 0 706 890 ;
+C -1 ; WX 500 ; N odieresis ; B 29 -10 470 623 ;
+C -1 ; WX 500 ; N oacute ; B 29 -10 470 678 ;
+C -1 ; WX 400 ; N degree ; B 57 390 343 676 ;
+C -1 ; WX 278 ; N igrave ; B -8 0 253 678 ;
+C -1 ; WX 500 ; N mu ; B 36 -218 512 450 ;
+C -1 ; WX 722 ; N Oacute ; B 34 -14 688 890 ;
+C -1 ; WX 500 ; N eth ; B 29 -10 471 686 ;
+C -1 ; WX 722 ; N Adieresis ; B 15 0 706 835 ;
+C -1 ; WX 722 ; N Yacute ; B 22 0 703 890 ;
+C -1 ; WX 200 ; N brokenbar ; B 67 -14 133 676 ;
+C -1 ; WX 750 ; N onehalf ; B 31 -14 746 676 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 283
+
+KPX A y -92
+KPX A w -92
+KPX A v -74
+KPX A u 0
+KPX A quoteright -111
+KPX A quotedblright 0
+KPX A p 0
+KPX A Y -105
+KPX A W -90
+KPX A V -135
+KPX A U -55
+KPX A T -111
+KPX A Q -55
+KPX A O -55
+KPX A G -40
+KPX A C -40
+
+KPX B period 0
+KPX B comma 0
+KPX B U -10
+KPX B A -35
+
+KPX D period 0
+KPX D comma 0
+KPX D Y -55
+KPX D W -30
+KPX D V -40
+KPX D A -40
+
+KPX F r 0
+KPX F period -80
+KPX F o -15
+KPX F i 0
+KPX F e 0
+KPX F comma -80
+KPX F a -15
+KPX F A -74
+
+KPX G period 0
+KPX G comma 0
+
+KPX J u 0
+KPX J period 0
+KPX J o 0
+KPX J e 0
+KPX J comma 0
+KPX J a 0
+KPX J A -60
+
+KPX K y -25
+KPX K u -15
+KPX K o -35
+KPX K e -25
+KPX K O -30
+
+KPX L y -55
+KPX L quoteright -92
+KPX L quotedblright 0
+KPX L Y -100
+KPX L W -74
+KPX L V -100
+KPX L T -92
+
+KPX N period 0
+KPX N comma 0
+KPX N A -35
+
+KPX O period 0
+KPX O comma 0
+KPX O Y -50
+KPX O X -40
+KPX O W -35
+KPX O V -50
+KPX O T -40
+KPX O A -35
+
+KPX P period -111
+KPX P o 0
+KPX P e 0
+KPX P comma -111
+KPX P a -15
+KPX P A -92
+
+KPX Q period 0
+KPX Q comma 0
+KPX Q U -10
+
+KPX R Y -65
+KPX R W -55
+KPX R V -80
+KPX R U -40
+KPX R T -60
+KPX R O -40
+
+KPX S period 0
+KPX S comma 0
+
+KPX T y -80
+KPX T w -80
+KPX T u -45
+KPX T semicolon -55
+KPX T r -35
+KPX T period -74
+KPX T o -80
+KPX T i -35
+KPX T hyphen -92
+KPX T h 0
+KPX T e -70
+KPX T comma -74
+KPX T colon -50
+KPX T a -80
+KPX T O -18
+KPX T A -93
+
+KPX U period 0
+KPX U comma 0
+KPX U A -40
+
+KPX V u -75
+KPX V semicolon -74
+KPX V period -129
+KPX V o -129
+KPX V i -60
+KPX V hyphen -100
+KPX V e -111
+KPX V comma -129
+KPX V colon -74
+KPX V a -111
+KPX V O -40
+KPX V G -15
+KPX V A -135
+
+KPX W y -73
+KPX W u -50
+KPX W semicolon -37
+KPX W period -92
+KPX W o -80
+KPX W i -40
+KPX W hyphen -65
+KPX W h 0
+KPX W e -80
+KPX W comma -92
+KPX W colon -37
+KPX W a -80
+KPX W O -10
+KPX W A -120
+
+KPX Y u -111
+KPX Y semicolon -92
+KPX Y period -129
+KPX Y o -110
+KPX Y i -55
+KPX Y hyphen -111
+KPX Y e -100
+KPX Y comma -129
+KPX Y colon -92
+KPX Y a -100
+KPX Y O -30
+KPX Y A -120
+
+KPX a y 0
+KPX a w -15
+KPX a v -20
+KPX a t 0
+KPX a p 0
+KPX a g 0
+KPX a b 0
+
+KPX b y 0
+KPX b v -15
+KPX b u -20
+KPX b period -40
+KPX b l 0
+KPX b comma 0
+KPX b b 0
+
+KPX c y -15
+KPX c period 0
+KPX c l 0
+KPX c k 0
+KPX c h 0
+KPX c comma 0
+
+KPX colon space 0
+
+KPX comma space 0
+KPX comma quoteright -70
+KPX comma quotedblright -70
+
+KPX d y 0
+KPX d w 0
+KPX d v 0
+KPX d period 0
+KPX d d 0
+KPX d comma 0
+
+KPX e y -15
+KPX e x -15
+KPX e w -25
+KPX e v -25
+KPX e period 0
+KPX e p 0
+KPX e g -15
+KPX e comma 0
+KPX e b 0
+
+KPX f quoteright 55
+KPX f quotedblright 0
+KPX f period 0
+KPX f o 0
+KPX f l 0
+KPX f i -20
+KPX f f -25
+KPX f e 0
+KPX f dotlessi -50
+KPX f comma 0
+KPX f a -10
+
+KPX g y 0
+KPX g r 0
+KPX g period 0
+KPX g o 0
+KPX g i 0
+KPX g g 0
+KPX g e 0
+KPX g comma 0
+KPX g a -5
+
+KPX h y -5
+
+KPX i v -25
+
+KPX k y -15
+KPX k o -10
+KPX k e -10
+
+KPX l y 0
+KPX l w -10
+
+KPX m y 0
+KPX m u 0
+
+KPX n y -15
+KPX n v -40
+KPX n u 0
+
+KPX o y -10
+KPX o x 0
+KPX o w -25
+KPX o v -15
+KPX o g 0
+
+KPX p y -10
+
+KPX period quoteright -70
+KPX period quotedblright -70
+
+KPX quotedblleft quoteleft 0
+KPX quotedblleft A -80
+
+KPX quotedblright space 0
+
+KPX quoteleft quoteleft -74
+KPX quoteleft A -80
+
+KPX quoteright v -50
+KPX quoteright t -18
+KPX quoteright space -74
+KPX quoteright s -55
+KPX quoteright r -50
+KPX quoteright quoteright -74
+KPX quoteright quotedblright 0
+KPX quoteright l -10
+KPX quoteright d -50
+
+KPX r y 0
+KPX r v 0
+KPX r u 0
+KPX r t 0
+KPX r s 0
+KPX r r 0
+KPX r q 0
+KPX r period -55
+KPX r p 0
+KPX r o 0
+KPX r n 0
+KPX r m 0
+KPX r l 0
+KPX r k 0
+KPX r i 0
+KPX r hyphen -20
+KPX r g -18
+KPX r e 0
+KPX r d 0
+KPX r comma -40
+KPX r c 0
+KPX r a 0
+
+KPX s w 0
+
+KPX space quoteleft 0
+KPX space quotedblleft 0
+KPX space Y -90
+KPX space W -30
+KPX space V -50
+KPX space T -18
+KPX space A -55
+
+KPX v period -65
+KPX v o -20
+KPX v e -15
+KPX v comma -65
+KPX v a -25
+
+KPX w period -65
+KPX w o -10
+KPX w h 0
+KPX w e 0
+KPX w comma -65
+KPX w a -10
+
+KPX x e -15
+
+KPX y period -65
+KPX y o 0
+KPX y e 0
+KPX y comma -65
+KPX y a 0
+
+KPX z o 0
+KPX z e 0
+EndKernPairs
+EndKernData
+StartComposites 58
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 195 212 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 195 212 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 195 212 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 195 212 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 185 187 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 195 212 ;
+CC Ccedilla 2 ; PCC C 0 0 ; PCC cedilla 167 0 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 139 212 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 139 212 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 139 212 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 139 212 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 0 212 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 0 212 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 0 212 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 0 212 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 195 212 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 195 212 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 195 212 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 195 212 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 195 212 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 195 212 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 112 212 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 195 212 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 195 212 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 195 212 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 195 212 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 195 212 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 195 212 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 139 212 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 56 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 56 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 56 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 56 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 56 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 56 0 ;
+CC ccedilla 2 ; PCC c 0 0 ; PCC cedilla 56 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 56 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex 56 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis 56 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 56 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -27 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -27 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -27 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -27 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 84 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 84 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 84 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 84 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 84 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde 84 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron 28 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 84 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 84 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 84 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 84 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 84 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 84 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 56 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/ZapfChancery-MediumItalic.afm b/tlt3.0/library/afm/ZapfChancery-MediumItalic.afm
new file mode 100644
index 0000000..7a8df29
--- /dev/null
+++ b/tlt3.0/library/afm/ZapfChancery-MediumItalic.afm
@@ -0,0 +1,481 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.
+Comment Creation Date: Fri Dec 28 16:35:46 1990
+Comment UniqueID 33936
+Comment VMusage 34559 41451
+FontName ZapfChancery-MediumItalic
+FullName ITC Zapf Chancery Medium Italic
+FamilyName ITC Zapf Chancery
+Weight Medium
+ItalicAngle -14
+IsFixedPitch false
+FontBBox -181 -314 1065 831
+UnderlinePosition -100
+UnderlineThickness 50
+Version 001.007
+Notice Copyright (c) 1985, 1987, 1989, 1990 Adobe Systems Incorporated. All Rights Reserved.ITC Zapf Chancery is a registered trademark of International Typeface Corporation.
+EncodingScheme AdobeStandardEncoding
+CapHeight 708
+XHeight 438
+Ascender 714
+Descender -314
+StartCharMetrics 228
+C 32 ; WX 220 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 280 ; N exclam ; B 119 -14 353 610 ;
+C 34 ; WX 220 ; N quotedbl ; B 120 343 333 610 ;
+C 35 ; WX 440 ; N numbersign ; B 83 0 521 594 ;
+C 36 ; WX 440 ; N dollar ; B 60 -144 508 709 ;
+C 37 ; WX 680 ; N percent ; B 132 -160 710 700 ;
+C 38 ; WX 780 ; N ampersand ; B 126 -16 915 610 ;
+C 39 ; WX 240 ; N quoteright ; B 168 343 338 610 ;
+C 40 ; WX 260 ; N parenleft ; B 96 -216 411 664 ;
+C 41 ; WX 220 ; N parenright ; B -13 -216 302 664 ;
+C 42 ; WX 420 ; N asterisk ; B 139 263 479 610 ;
+C 43 ; WX 520 ; N plus ; B 117 0 543 426 ;
+C 44 ; WX 220 ; N comma ; B 25 -140 213 148 ;
+C 45 ; WX 280 ; N hyphen ; B 69 190 334 248 ;
+C 46 ; WX 220 ; N period ; B 102 -14 228 128 ;
+C 47 ; WX 340 ; N slash ; B 74 -16 458 610 ;
+C 48 ; WX 440 ; N zero ; B 79 -16 538 610 ;
+C 49 ; WX 440 ; N one ; B 41 0 428 610 ;
+C 50 ; WX 440 ; N two ; B 17 -16 485 610 ;
+C 51 ; WX 440 ; N three ; B 1 -16 485 610 ;
+C 52 ; WX 440 ; N four ; B 77 -35 499 610 ;
+C 53 ; WX 440 ; N five ; B 60 -16 595 679 ;
+C 54 ; WX 440 ; N six ; B 90 -16 556 610 ;
+C 55 ; WX 440 ; N seven ; B 157 -33 561 645 ;
+C 56 ; WX 440 ; N eight ; B 65 -16 529 610 ;
+C 57 ; WX 440 ; N nine ; B 32 -16 517 610 ;
+C 58 ; WX 260 ; N colon ; B 98 -14 296 438 ;
+C 59 ; WX 240 ; N semicolon ; B 29 -140 299 438 ;
+C 60 ; WX 520 ; N less ; B 139 0 527 468 ;
+C 61 ; WX 520 ; N equal ; B 117 86 543 340 ;
+C 62 ; WX 520 ; N greater ; B 139 0 527 468 ;
+C 63 ; WX 380 ; N question ; B 150 -14 455 610 ;
+C 64 ; WX 700 ; N at ; B 127 -16 753 610 ;
+C 65 ; WX 620 ; N A ; B 13 -16 697 632 ;
+C 66 ; WX 600 ; N B ; B 85 -6 674 640 ;
+C 67 ; WX 520 ; N C ; B 93 -16 631 610 ;
+C 68 ; WX 700 ; N D ; B 86 -6 768 640 ;
+C 69 ; WX 620 ; N E ; B 91 -12 709 618 ;
+C 70 ; WX 580 ; N F ; B 120 -118 793 629 ;
+C 71 ; WX 620 ; N G ; B 148 -242 709 610 ;
+C 72 ; WX 680 ; N H ; B 18 -16 878 708 ;
+C 73 ; WX 380 ; N I ; B 99 0 504 594 ;
+C 74 ; WX 400 ; N J ; B -14 -147 538 594 ;
+C 75 ; WX 660 ; N K ; B 53 -153 844 610 ;
+C 76 ; WX 580 ; N L ; B 53 -16 657 610 ;
+C 77 ; WX 840 ; N M ; B 58 -16 1020 722 ;
+C 78 ; WX 700 ; N N ; B 85 -168 915 708 ;
+C 79 ; WX 600 ; N O ; B 94 -16 660 610 ;
+C 80 ; WX 540 ; N P ; B 42 0 658 628 ;
+C 81 ; WX 600 ; N Q ; B 84 -177 775 610 ;
+C 82 ; WX 600 ; N R ; B 58 -168 805 640 ;
+C 83 ; WX 460 ; N S ; B 45 -81 558 610 ;
+C 84 ; WX 500 ; N T ; B 63 0 744 667 ;
+C 85 ; WX 740 ; N U ; B 126 -16 792 617 ;
+C 86 ; WX 640 ; N V ; B 124 -16 810 714 ;
+C 87 ; WX 880 ; N W ; B 94 -16 1046 723 ;
+C 88 ; WX 560 ; N X ; B -30 -16 699 610 ;
+C 89 ; WX 560 ; N Y ; B 41 -168 774 647 ;
+C 90 ; WX 620 ; N Z ; B 42 -19 669 624 ;
+C 91 ; WX 240 ; N bracketleft ; B -13 -207 405 655 ;
+C 92 ; WX 480 ; N backslash ; B 140 -16 524 610 ;
+C 93 ; WX 320 ; N bracketright ; B -27 -207 391 655 ;
+C 94 ; WX 520 ; N asciicircum ; B 132 239 532 594 ;
+C 95 ; WX 500 ; N underscore ; B 0 -125 500 -75 ;
+C 96 ; WX 240 ; N quoteleft ; B 169 343 339 610 ;
+C 97 ; WX 420 ; N a ; B 92 -15 485 438 ;
+C 98 ; WX 420 ; N b ; B 82 -23 492 714 ;
+C 99 ; WX 340 ; N c ; B 87 -14 406 438 ;
+C 100 ; WX 440 ; N d ; B 102 -14 651 714 ;
+C 101 ; WX 340 ; N e ; B 87 -14 403 438 ;
+C 102 ; WX 320 ; N f ; B -119 -314 547 714 ; L i fi ; L l fl ;
+C 103 ; WX 400 ; N g ; B -108 -314 503 438 ;
+C 104 ; WX 440 ; N h ; B 55 -14 524 714 ;
+C 105 ; WX 240 ; N i ; B 100 -14 341 635 ;
+C 106 ; WX 220 ; N j ; B -112 -314 332 635 ;
+C 107 ; WX 440 ; N k ; B 87 -184 628 714 ;
+C 108 ; WX 240 ; N l ; B 102 -14 480 714 ;
+C 109 ; WX 620 ; N m ; B 86 -14 704 438 ;
+C 110 ; WX 460 ; N n ; B 101 -14 544 438 ;
+C 111 ; WX 400 ; N o ; B 87 -14 449 438 ;
+C 112 ; WX 440 ; N p ; B -23 -314 484 432 ;
+C 113 ; WX 400 ; N q ; B 87 -300 490 510 ;
+C 114 ; WX 300 ; N r ; B 101 -14 424 438 ;
+C 115 ; WX 320 ; N s ; B 46 -14 403 438 ;
+C 116 ; WX 320 ; N t ; B 106 -14 426 539 ;
+C 117 ; WX 460 ; N u ; B 102 -14 528 438 ;
+C 118 ; WX 440 ; N v ; B 87 -14 533 488 ;
+C 119 ; WX 680 ; N w ; B 87 -14 782 488 ;
+C 120 ; WX 420 ; N x ; B 70 -195 589 438 ;
+C 121 ; WX 400 ; N y ; B -24 -314 483 438 ;
+C 122 ; WX 440 ; N z ; B 26 -14 508 445 ;
+C 123 ; WX 240 ; N braceleft ; B 55 -207 383 655 ;
+C 124 ; WX 520 ; N bar ; B 320 -16 378 714 ;
+C 125 ; WX 240 ; N braceright ; B -10 -207 318 655 ;
+C 126 ; WX 520 ; N asciitilde ; B 123 186 539 320 ;
+C 161 ; WX 280 ; N exclamdown ; B 72 -186 306 438 ;
+C 162 ; WX 440 ; N cent ; B 122 -134 476 543 ;
+C 163 ; WX 440 ; N sterling ; B -16 -52 506 610 ;
+C 164 ; WX 60 ; N fraction ; B -181 -16 320 610 ;
+C 165 ; WX 440 ; N yen ; B -1 -168 613 647 ;
+C 166 ; WX 440 ; N florin ; B -64 -314 582 610 ;
+C 167 ; WX 420 ; N section ; B 53 -215 514 610 ;
+C 168 ; WX 440 ; N currency ; B 50 85 474 509 ;
+C 169 ; WX 160 ; N quotesingle ; B 145 343 215 610 ;
+C 170 ; WX 340 ; N quotedblleft ; B 169 343 464 610 ;
+C 171 ; WX 340 ; N guillemotleft ; B 98 24 356 414 ;
+C 172 ; WX 240 ; N guilsinglleft ; B 98 24 258 414 ;
+C 173 ; WX 260 ; N guilsinglright ; B 106 24 266 414 ;
+C 174 ; WX 520 ; N fi ; B -124 -314 605 714 ;
+C 175 ; WX 520 ; N fl ; B -124 -314 670 714 ;
+C 177 ; WX 500 ; N endash ; B 51 199 565 239 ;
+C 178 ; WX 460 ; N dagger ; B 138 -37 568 610 ;
+C 179 ; WX 480 ; N daggerdbl ; B 138 -59 533 610 ;
+C 180 ; WX 220 ; N periodcentered ; B 139 208 241 310 ;
+C 182 ; WX 500 ; N paragraph ; B 105 -199 638 594 ;
+C 183 ; WX 600 ; N bullet ; B 228 149 524 445 ;
+C 184 ; WX 180 ; N quotesinglbase ; B 21 -121 191 146 ;
+C 185 ; WX 280 ; N quotedblbase ; B -14 -121 281 146 ;
+C 186 ; WX 360 ; N quotedblright ; B 158 343 453 610 ;
+C 187 ; WX 380 ; N guillemotright ; B 117 24 375 414 ;
+C 188 ; WX 1000 ; N ellipsis ; B 124 -14 916 128 ;
+C 189 ; WX 960 ; N perthousand ; B 112 -160 1005 700 ;
+C 191 ; WX 400 ; N questiondown ; B 82 -186 387 438 ;
+C 193 ; WX 220 ; N grave ; B 193 492 339 659 ;
+C 194 ; WX 300 ; N acute ; B 265 492 422 659 ;
+C 195 ; WX 340 ; N circumflex ; B 223 482 443 649 ;
+C 196 ; WX 440 ; N tilde ; B 243 543 522 619 ;
+C 197 ; WX 440 ; N macron ; B 222 544 465 578 ;
+C 198 ; WX 440 ; N breve ; B 253 522 501 631 ;
+C 199 ; WX 220 ; N dotaccent ; B 236 522 328 610 ;
+C 200 ; WX 360 ; N dieresis ; B 243 522 469 610 ;
+C 202 ; WX 300 ; N ring ; B 240 483 416 659 ;
+C 203 ; WX 300 ; N cedilla ; B 12 -191 184 6 ;
+C 205 ; WX 400 ; N hungarumlaut ; B 208 492 495 659 ;
+C 206 ; WX 280 ; N ogonek ; B 38 -191 233 6 ;
+C 207 ; WX 340 ; N caron ; B 254 492 474 659 ;
+C 208 ; WX 1000 ; N emdash ; B 51 199 1065 239 ;
+C 225 ; WX 740 ; N AE ; B -21 -16 799 594 ;
+C 227 ; WX 260 ; N ordfeminine ; B 111 338 386 610 ;
+C 232 ; WX 580 ; N Lslash ; B 49 -16 657 610 ;
+C 233 ; WX 660 ; N Oslash ; B 83 -78 751 672 ;
+C 234 ; WX 820 ; N OE ; B 63 -16 909 610 ;
+C 235 ; WX 260 ; N ordmasculine ; B 128 339 373 610 ;
+C 241 ; WX 540 ; N ae ; B 67 -14 624 468 ;
+C 245 ; WX 240 ; N dotlessi ; B 100 -14 306 438 ;
+C 248 ; WX 300 ; N lslash ; B 121 -14 515 714 ;
+C 249 ; WX 440 ; N oslash ; B 46 -64 540 488 ;
+C 250 ; WX 560 ; N oe ; B 78 -14 628 438 ;
+C 251 ; WX 420 ; N germandbls ; B -127 -314 542 714 ;
+C -1 ; WX 340 ; N ecircumflex ; B 87 -14 433 649 ;
+C -1 ; WX 340 ; N edieresis ; B 87 -14 449 610 ;
+C -1 ; WX 420 ; N aacute ; B 92 -15 492 659 ;
+C -1 ; WX 740 ; N registered ; B 137 -16 763 610 ;
+C -1 ; WX 240 ; N icircumflex ; B 100 -14 363 649 ;
+C -1 ; WX 460 ; N udieresis ; B 102 -14 528 610 ;
+C -1 ; WX 400 ; N ograve ; B 87 -14 449 659 ;
+C -1 ; WX 460 ; N uacute ; B 102 -14 528 659 ;
+C -1 ; WX 460 ; N ucircumflex ; B 102 -14 528 649 ;
+C -1 ; WX 620 ; N Aacute ; B 13 -16 702 821 ;
+C -1 ; WX 240 ; N igrave ; B 100 -14 306 659 ;
+C -1 ; WX 380 ; N Icircumflex ; B 99 0 504 821 ;
+C -1 ; WX 340 ; N ccedilla ; B 62 -191 406 438 ;
+C -1 ; WX 420 ; N adieresis ; B 92 -15 485 610 ;
+C -1 ; WX 620 ; N Ecircumflex ; B 91 -12 709 821 ;
+C -1 ; WX 320 ; N scaron ; B 46 -14 464 659 ;
+C -1 ; WX 440 ; N thorn ; B -38 -314 505 714 ;
+C -1 ; WX 1000 ; N trademark ; B 127 187 1046 594 ;
+C -1 ; WX 340 ; N egrave ; B 87 -14 403 659 ;
+C -1 ; WX 264 ; N threesuperior ; B 59 234 348 610 ;
+C -1 ; WX 440 ; N zcaron ; B 26 -14 514 659 ;
+C -1 ; WX 420 ; N atilde ; B 92 -15 522 619 ;
+C -1 ; WX 420 ; N aring ; B 92 -15 485 659 ;
+C -1 ; WX 400 ; N ocircumflex ; B 87 -14 453 649 ;
+C -1 ; WX 620 ; N Edieresis ; B 91 -12 709 762 ;
+C -1 ; WX 660 ; N threequarters ; B 39 -16 706 610 ;
+C -1 ; WX 400 ; N ydieresis ; B -24 -314 483 610 ;
+C -1 ; WX 400 ; N yacute ; B -24 -314 483 659 ;
+C -1 ; WX 240 ; N iacute ; B 100 -14 392 659 ;
+C -1 ; WX 620 ; N Acircumflex ; B 13 -16 697 821 ;
+C -1 ; WX 740 ; N Uacute ; B 126 -16 792 821 ;
+C -1 ; WX 340 ; N eacute ; B 87 -14 462 659 ;
+C -1 ; WX 600 ; N Ograve ; B 94 -16 660 821 ;
+C -1 ; WX 420 ; N agrave ; B 92 -15 485 659 ;
+C -1 ; WX 740 ; N Udieresis ; B 126 -16 792 762 ;
+C -1 ; WX 420 ; N acircumflex ; B 92 -15 485 649 ;
+C -1 ; WX 380 ; N Igrave ; B 99 0 504 821 ;
+C -1 ; WX 264 ; N twosuperior ; B 72 234 354 610 ;
+C -1 ; WX 740 ; N Ugrave ; B 126 -16 792 821 ;
+C -1 ; WX 660 ; N onequarter ; B 56 -16 702 610 ;
+C -1 ; WX 740 ; N Ucircumflex ; B 126 -16 792 821 ;
+C -1 ; WX 460 ; N Scaron ; B 45 -81 594 831 ;
+C -1 ; WX 380 ; N Idieresis ; B 99 0 519 762 ;
+C -1 ; WX 240 ; N idieresis ; B 100 -14 369 610 ;
+C -1 ; WX 620 ; N Egrave ; B 91 -12 709 821 ;
+C -1 ; WX 600 ; N Oacute ; B 94 -16 660 821 ;
+C -1 ; WX 520 ; N divide ; B 117 -14 543 440 ;
+C -1 ; WX 620 ; N Atilde ; B 13 -16 702 771 ;
+C -1 ; WX 620 ; N Aring ; B 13 -16 697 831 ;
+C -1 ; WX 600 ; N Odieresis ; B 94 -16 660 762 ;
+C -1 ; WX 620 ; N Adieresis ; B 13 -16 709 762 ;
+C -1 ; WX 700 ; N Ntilde ; B 85 -168 915 761 ;
+C -1 ; WX 620 ; N Zcaron ; B 42 -19 669 831 ;
+C -1 ; WX 540 ; N Thorn ; B 52 0 647 623 ;
+C -1 ; WX 380 ; N Iacute ; B 99 0 532 821 ;
+C -1 ; WX 520 ; N plusminus ; B 117 0 543 436 ;
+C -1 ; WX 520 ; N multiply ; B 133 16 527 410 ;
+C -1 ; WX 620 ; N Eacute ; B 91 -12 709 821 ;
+C -1 ; WX 560 ; N Ydieresis ; B 41 -168 774 762 ;
+C -1 ; WX 264 ; N onesuperior ; B 83 244 311 610 ;
+C -1 ; WX 460 ; N ugrave ; B 102 -14 528 659 ;
+C -1 ; WX 520 ; N logicalnot ; B 117 86 543 340 ;
+C -1 ; WX 460 ; N ntilde ; B 101 -14 544 619 ;
+C -1 ; WX 600 ; N Otilde ; B 94 -16 660 761 ;
+C -1 ; WX 400 ; N otilde ; B 87 -14 502 619 ;
+C -1 ; WX 520 ; N Ccedilla ; B 93 -191 631 610 ;
+C -1 ; WX 620 ; N Agrave ; B 13 -16 697 821 ;
+C -1 ; WX 660 ; N onehalf ; B 56 -16 702 610 ;
+C -1 ; WX 700 ; N Eth ; B 86 -6 768 640 ;
+C -1 ; WX 400 ; N degree ; B 171 324 457 610 ;
+C -1 ; WX 560 ; N Yacute ; B 41 -168 774 821 ;
+C -1 ; WX 600 ; N Ocircumflex ; B 94 -16 660 821 ;
+C -1 ; WX 400 ; N oacute ; B 87 -14 482 659 ;
+C -1 ; WX 460 ; N mu ; B 7 -314 523 438 ;
+C -1 ; WX 520 ; N minus ; B 117 184 543 242 ;
+C -1 ; WX 400 ; N eth ; B 87 -14 522 714 ;
+C -1 ; WX 400 ; N odieresis ; B 87 -14 479 610 ;
+C -1 ; WX 740 ; N copyright ; B 137 -16 763 610 ;
+C -1 ; WX 520 ; N brokenbar ; B 320 -16 378 714 ;
+EndCharMetrics
+StartKernData
+StartKernPairs 131
+
+KPX A quoteright -40
+KPX A quotedblright -40
+KPX A U -10
+KPX A T 10
+KPX A Q 10
+KPX A O 10
+KPX A G -30
+KPX A C 20
+
+KPX D period -30
+KPX D comma -20
+KPX D Y 10
+KPX D A -10
+
+KPX F period -40
+KPX F i 10
+KPX F comma -30
+
+KPX G period -20
+KPX G comma -10
+
+KPX J period -20
+KPX J comma -10
+
+KPX K u -20
+KPX K o -20
+KPX K e -20
+
+KPX L y -10
+KPX L quoteright -25
+KPX L quotedblright -25
+KPX L W -10
+KPX L V -20
+
+KPX O period -20
+KPX O comma -10
+KPX O Y 10
+KPX O T 20
+KPX O A -20
+
+KPX P period -50
+KPX P o -10
+KPX P e -10
+KPX P comma -40
+KPX P a -20
+KPX P A -10
+
+KPX Q U -10
+
+KPX R Y 10
+KPX R W 10
+KPX R T 20
+
+KPX T o -20
+KPX T i 20
+KPX T hyphen -20
+KPX T h 20
+KPX T e -20
+KPX T a -20
+KPX T O 30
+KPX T A 10
+
+KPX V period -100
+KPX V o -20
+KPX V e -20
+KPX V comma -90
+KPX V a -20
+KPX V O 10
+KPX V G -20
+
+KPX W period -50
+KPX W o -20
+KPX W i 10
+KPX W h 10
+KPX W e -20
+KPX W comma -40
+KPX W a -20
+KPX W O 10
+
+KPX Y u -20
+KPX Y period -50
+KPX Y o -50
+KPX Y i 10
+KPX Y e -40
+KPX Y comma -40
+KPX Y a -60
+
+KPX b period -30
+KPX b l -20
+KPX b comma -20
+KPX b b -20
+
+KPX c k -10
+
+KPX comma quoteright -70
+KPX comma quotedblright -70
+
+KPX d w -20
+KPX d v -10
+KPX d d -40
+
+KPX e y 10
+
+KPX f quoteright 30
+KPX f quotedblright 30
+KPX f period -50
+KPX f f -50
+KPX f e -10
+KPX f comma -40
+KPX f a -20
+
+KPX g y 10
+KPX g period -30
+KPX g i 10
+KPX g e 10
+KPX g comma -20
+KPX g a 10
+
+KPX k y 10
+KPX k o -10
+KPX k e -20
+
+KPX m y 10
+KPX m u 10
+
+KPX n y 20
+
+KPX o period -30
+KPX o comma -20
+
+KPX p period -30
+KPX p p -10
+KPX p comma -20
+
+KPX period quoteright -80
+KPX period quotedblright -80
+
+KPX quotedblleft quoteleft 20
+KPX quotedblleft A 10
+
+KPX quoteleft quoteleft -115
+KPX quoteleft A 10
+
+KPX quoteright v 30
+KPX quoteright t 20
+KPX quoteright s -25
+KPX quoteright r 30
+KPX quoteright quoteright -115
+KPX quoteright quotedblright 20
+KPX quoteright l 20
+
+KPX r period -50
+KPX r i 10
+KPX r comma -40
+
+KPX s period -20
+KPX s comma -10
+
+KPX v period -30
+KPX v comma -20
+
+KPX w period -30
+KPX w o 10
+KPX w h 20
+KPX w comma -20
+EndKernPairs
+EndKernData
+StartComposites 56
+CC Aacute 2 ; PCC A 0 0 ; PCC acute 280 162 ;
+CC Acircumflex 2 ; PCC A 0 0 ; PCC circumflex 240 172 ;
+CC Adieresis 2 ; PCC A 0 0 ; PCC dieresis 240 152 ;
+CC Agrave 2 ; PCC A 0 0 ; PCC grave 250 162 ;
+CC Aring 2 ; PCC A 0 0 ; PCC ring 260 172 ;
+CC Atilde 2 ; PCC A 0 0 ; PCC tilde 180 152 ;
+CC Eacute 2 ; PCC E 0 0 ; PCC acute 230 162 ;
+CC Ecircumflex 2 ; PCC E 0 0 ; PCC circumflex 180 172 ;
+CC Edieresis 2 ; PCC E 0 0 ; PCC dieresis 170 152 ;
+CC Egrave 2 ; PCC E 0 0 ; PCC grave 220 162 ;
+CC Iacute 2 ; PCC I 0 0 ; PCC acute 110 162 ;
+CC Icircumflex 2 ; PCC I 0 0 ; PCC circumflex 60 172 ;
+CC Idieresis 2 ; PCC I 0 0 ; PCC dieresis 50 152 ;
+CC Igrave 2 ; PCC I 0 0 ; PCC grave 100 162 ;
+CC Ntilde 2 ; PCC N 0 0 ; PCC tilde 210 142 ;
+CC Oacute 2 ; PCC O 0 0 ; PCC acute 160 162 ;
+CC Ocircumflex 2 ; PCC O 0 0 ; PCC circumflex 130 172 ;
+CC Odieresis 2 ; PCC O 0 0 ; PCC dieresis 120 152 ;
+CC Ograve 2 ; PCC O 0 0 ; PCC grave 150 162 ;
+CC Otilde 2 ; PCC O 0 0 ; PCC tilde 90 142 ;
+CC Scaron 2 ; PCC S 0 0 ; PCC caron 120 172 ;
+CC Uacute 2 ; PCC U 0 0 ; PCC acute 310 162 ;
+CC Ucircumflex 2 ; PCC U 0 0 ; PCC circumflex 260 172 ;
+CC Udieresis 2 ; PCC U 0 0 ; PCC dieresis 260 152 ;
+CC Ugrave 2 ; PCC U 0 0 ; PCC grave 270 162 ;
+CC Yacute 2 ; PCC Y 0 0 ; PCC acute 220 162 ;
+CC Ydieresis 2 ; PCC Y 0 0 ; PCC dieresis 170 152 ;
+CC Zcaron 2 ; PCC Z 0 0 ; PCC caron 130 172 ;
+CC aacute 2 ; PCC a 0 0 ; PCC acute 70 0 ;
+CC acircumflex 2 ; PCC a 0 0 ; PCC circumflex 20 0 ;
+CC adieresis 2 ; PCC a 0 0 ; PCC dieresis 10 0 ;
+CC agrave 2 ; PCC a 0 0 ; PCC grave 80 0 ;
+CC aring 2 ; PCC a 0 0 ; PCC ring 60 0 ;
+CC atilde 2 ; PCC a 0 0 ; PCC tilde 0 0 ;
+CC eacute 2 ; PCC e 0 0 ; PCC acute 40 0 ;
+CC ecircumflex 2 ; PCC e 0 0 ; PCC circumflex -10 0 ;
+CC edieresis 2 ; PCC e 0 0 ; PCC dieresis -20 0 ;
+CC egrave 2 ; PCC e 0 0 ; PCC grave 30 0 ;
+CC iacute 2 ; PCC dotlessi 0 0 ; PCC acute -30 0 ;
+CC icircumflex 2 ; PCC dotlessi 0 0 ; PCC circumflex -80 0 ;
+CC idieresis 2 ; PCC dotlessi 0 0 ; PCC dieresis -100 0 ;
+CC igrave 2 ; PCC dotlessi 0 0 ; PCC grave -40 0 ;
+CC ntilde 2 ; PCC n 0 0 ; PCC tilde 10 0 ;
+CC oacute 2 ; PCC o 0 0 ; PCC acute 60 0 ;
+CC ocircumflex 2 ; PCC o 0 0 ; PCC circumflex 10 0 ;
+CC odieresis 2 ; PCC o 0 0 ; PCC dieresis 10 0 ;
+CC ograve 2 ; PCC o 0 0 ; PCC grave 60 0 ;
+CC otilde 2 ; PCC o 0 0 ; PCC tilde -20 0 ;
+CC scaron 2 ; PCC s 0 0 ; PCC caron -10 0 ;
+CC uacute 2 ; PCC u 0 0 ; PCC acute 70 0 ;
+CC ucircumflex 2 ; PCC u 0 0 ; PCC circumflex 30 0 ;
+CC udieresis 2 ; PCC u 0 0 ; PCC dieresis 20 0 ;
+CC ugrave 2 ; PCC u 0 0 ; PCC grave 50 0 ;
+CC yacute 2 ; PCC y 0 0 ; PCC acute 60 0 ;
+CC ydieresis 2 ; PCC y 0 0 ; PCC dieresis 0 0 ;
+CC zcaron 2 ; PCC z 0 0 ; PCC caron 40 0 ;
+EndComposites
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/afm/ZapfDingbats.afm b/tlt3.0/library/afm/ZapfDingbats.afm
new file mode 100644
index 0000000..24fd05e
--- /dev/null
+++ b/tlt3.0/library/afm/ZapfDingbats.afm
@@ -0,0 +1,223 @@
+StartFontMetrics 2.0
+Comment Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.
+Comment Creation Date: Fri Dec 1 12:57:42 1989
+Comment UniqueID 26200
+Comment VMusage 39281 49041
+FontName ZapfDingbats
+FullName ITC Zapf Dingbats
+FamilyName ITC Zapf Dingbats
+Weight Medium
+ItalicAngle 0
+IsFixedPitch false
+FontBBox -1 -143 981 820
+UnderlinePosition -98
+UnderlineThickness 54
+Version 001.004
+Notice Copyright (c) 1985, 1987, 1988, 1989 Adobe Systems Incorporated. All rights reserved.ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
+EncodingScheme FontSpecific
+StartCharMetrics 202
+C 32 ; WX 278 ; N space ; B 0 0 0 0 ;
+C 33 ; WX 974 ; N a1 ; B 35 72 939 621 ;
+C 34 ; WX 961 ; N a2 ; B 35 81 927 611 ;
+C 35 ; WX 974 ; N a202 ; B 35 72 939 621 ;
+C 36 ; WX 980 ; N a3 ; B 35 0 945 692 ;
+C 37 ; WX 719 ; N a4 ; B 34 139 685 566 ;
+C 38 ; WX 789 ; N a5 ; B 35 -14 755 705 ;
+C 39 ; WX 790 ; N a119 ; B 35 -14 755 705 ;
+C 40 ; WX 791 ; N a118 ; B 35 -13 761 705 ;
+C 41 ; WX 690 ; N a117 ; B 35 138 655 553 ;
+C 42 ; WX 960 ; N a11 ; B 35 123 925 568 ;
+C 43 ; WX 939 ; N a12 ; B 35 134 904 559 ;
+C 44 ; WX 549 ; N a13 ; B 29 -11 516 705 ;
+C 45 ; WX 855 ; N a14 ; B 34 59 820 632 ;
+C 46 ; WX 911 ; N a15 ; B 35 50 876 642 ;
+C 47 ; WX 933 ; N a16 ; B 35 139 899 550 ;
+C 48 ; WX 911 ; N a105 ; B 35 50 876 642 ;
+C 49 ; WX 945 ; N a17 ; B 35 139 909 553 ;
+C 50 ; WX 974 ; N a18 ; B 35 104 938 587 ;
+C 51 ; WX 755 ; N a19 ; B 34 -13 721 705 ;
+C 52 ; WX 846 ; N a20 ; B 36 -14 811 705 ;
+C 53 ; WX 762 ; N a21 ; B 35 0 727 692 ;
+C 54 ; WX 761 ; N a22 ; B 35 0 727 692 ;
+C 55 ; WX 571 ; N a23 ; B -1 -68 571 661 ;
+C 56 ; WX 677 ; N a24 ; B 36 -13 642 705 ;
+C 57 ; WX 763 ; N a25 ; B 35 0 728 692 ;
+C 58 ; WX 760 ; N a26 ; B 35 0 726 692 ;
+C 59 ; WX 759 ; N a27 ; B 35 0 725 692 ;
+C 60 ; WX 754 ; N a28 ; B 35 0 720 692 ;
+C 61 ; WX 494 ; N a6 ; B 35 0 460 692 ;
+C 62 ; WX 552 ; N a7 ; B 35 0 517 692 ;
+C 63 ; WX 537 ; N a8 ; B 35 0 503 692 ;
+C 64 ; WX 577 ; N a9 ; B 35 96 542 596 ;
+C 65 ; WX 692 ; N a10 ; B 35 -14 657 705 ;
+C 66 ; WX 786 ; N a29 ; B 35 -14 751 705 ;
+C 67 ; WX 788 ; N a30 ; B 35 -14 752 705 ;
+C 68 ; WX 788 ; N a31 ; B 35 -14 753 705 ;
+C 69 ; WX 790 ; N a32 ; B 35 -14 756 705 ;
+C 70 ; WX 793 ; N a33 ; B 35 -13 759 705 ;
+C 71 ; WX 794 ; N a34 ; B 35 -13 759 705 ;
+C 72 ; WX 816 ; N a35 ; B 35 -14 782 705 ;
+C 73 ; WX 823 ; N a36 ; B 35 -14 787 705 ;
+C 74 ; WX 789 ; N a37 ; B 35 -14 754 705 ;
+C 75 ; WX 841 ; N a38 ; B 35 -14 807 705 ;
+C 76 ; WX 823 ; N a39 ; B 35 -14 789 705 ;
+C 77 ; WX 833 ; N a40 ; B 35 -14 798 705 ;
+C 78 ; WX 816 ; N a41 ; B 35 -13 782 705 ;
+C 79 ; WX 831 ; N a42 ; B 35 -14 796 705 ;
+C 80 ; WX 923 ; N a43 ; B 35 -14 888 705 ;
+C 81 ; WX 744 ; N a44 ; B 35 0 710 692 ;
+C 82 ; WX 723 ; N a45 ; B 35 0 688 692 ;
+C 83 ; WX 749 ; N a46 ; B 35 0 714 692 ;
+C 84 ; WX 790 ; N a47 ; B 34 -14 756 705 ;
+C 85 ; WX 792 ; N a48 ; B 35 -14 758 705 ;
+C 86 ; WX 695 ; N a49 ; B 35 -14 661 706 ;
+C 87 ; WX 776 ; N a50 ; B 35 -6 741 699 ;
+C 88 ; WX 768 ; N a51 ; B 35 -7 734 699 ;
+C 89 ; WX 792 ; N a52 ; B 35 -14 757 705 ;
+C 90 ; WX 759 ; N a53 ; B 35 0 725 692 ;
+C 91 ; WX 707 ; N a54 ; B 35 -13 672 704 ;
+C 92 ; WX 708 ; N a55 ; B 35 -14 672 705 ;
+C 93 ; WX 682 ; N a56 ; B 35 -14 647 705 ;
+C 94 ; WX 701 ; N a57 ; B 35 -14 666 705 ;
+C 95 ; WX 826 ; N a58 ; B 35 -14 791 705 ;
+C 96 ; WX 815 ; N a59 ; B 35 -14 780 705 ;
+C 97 ; WX 789 ; N a60 ; B 35 -14 754 705 ;
+C 98 ; WX 789 ; N a61 ; B 35 -14 754 705 ;
+C 99 ; WX 707 ; N a62 ; B 34 -14 673 705 ;
+C 100 ; WX 687 ; N a63 ; B 36 0 651 692 ;
+C 101 ; WX 696 ; N a64 ; B 35 0 661 691 ;
+C 102 ; WX 689 ; N a65 ; B 35 0 655 692 ;
+C 103 ; WX 786 ; N a66 ; B 34 -14 751 705 ;
+C 104 ; WX 787 ; N a67 ; B 35 -14 752 705 ;
+C 105 ; WX 713 ; N a68 ; B 35 -14 678 705 ;
+C 106 ; WX 791 ; N a69 ; B 35 -14 756 705 ;
+C 107 ; WX 785 ; N a70 ; B 36 -14 751 705 ;
+C 108 ; WX 791 ; N a71 ; B 35 -14 757 705 ;
+C 109 ; WX 873 ; N a72 ; B 35 -14 838 705 ;
+C 110 ; WX 761 ; N a73 ; B 35 0 726 692 ;
+C 111 ; WX 762 ; N a74 ; B 35 0 727 692 ;
+C 112 ; WX 762 ; N a203 ; B 35 0 727 692 ;
+C 113 ; WX 759 ; N a75 ; B 35 0 725 692 ;
+C 114 ; WX 759 ; N a204 ; B 35 0 725 692 ;
+C 115 ; WX 892 ; N a76 ; B 35 0 858 705 ;
+C 116 ; WX 892 ; N a77 ; B 35 -14 858 692 ;
+C 117 ; WX 788 ; N a78 ; B 35 -14 754 705 ;
+C 118 ; WX 784 ; N a79 ; B 35 -14 749 705 ;
+C 119 ; WX 438 ; N a81 ; B 35 -14 403 705 ;
+C 120 ; WX 138 ; N a82 ; B 35 0 104 692 ;
+C 121 ; WX 277 ; N a83 ; B 35 0 242 692 ;
+C 122 ; WX 415 ; N a84 ; B 35 0 380 692 ;
+C 123 ; WX 392 ; N a97 ; B 35 263 357 705 ;
+C 124 ; WX 392 ; N a98 ; B 34 263 357 705 ;
+C 125 ; WX 668 ; N a99 ; B 35 263 633 705 ;
+C 126 ; WX 668 ; N a100 ; B 36 263 634 705 ;
+C 161 ; WX 732 ; N a101 ; B 35 -143 697 806 ;
+C 162 ; WX 544 ; N a102 ; B 56 -14 488 706 ;
+C 163 ; WX 544 ; N a103 ; B 34 -14 508 705 ;
+C 164 ; WX 910 ; N a104 ; B 35 40 875 651 ;
+C 165 ; WX 667 ; N a106 ; B 35 -14 633 705 ;
+C 166 ; WX 760 ; N a107 ; B 35 -14 726 705 ;
+C 167 ; WX 760 ; N a108 ; B 0 121 758 569 ;
+C 168 ; WX 776 ; N a112 ; B 35 0 741 705 ;
+C 169 ; WX 595 ; N a111 ; B 34 -14 560 705 ;
+C 170 ; WX 694 ; N a110 ; B 35 -14 659 705 ;
+C 171 ; WX 626 ; N a109 ; B 34 0 591 705 ;
+C 172 ; WX 788 ; N a120 ; B 35 -14 754 705 ;
+C 173 ; WX 788 ; N a121 ; B 35 -14 754 705 ;
+C 174 ; WX 788 ; N a122 ; B 35 -14 754 705 ;
+C 175 ; WX 788 ; N a123 ; B 35 -14 754 705 ;
+C 176 ; WX 788 ; N a124 ; B 35 -14 754 705 ;
+C 177 ; WX 788 ; N a125 ; B 35 -14 754 705 ;
+C 178 ; WX 788 ; N a126 ; B 35 -14 754 705 ;
+C 179 ; WX 788 ; N a127 ; B 35 -14 754 705 ;
+C 180 ; WX 788 ; N a128 ; B 35 -14 754 705 ;
+C 181 ; WX 788 ; N a129 ; B 35 -14 754 705 ;
+C 182 ; WX 788 ; N a130 ; B 35 -14 754 705 ;
+C 183 ; WX 788 ; N a131 ; B 35 -14 754 705 ;
+C 184 ; WX 788 ; N a132 ; B 35 -14 754 705 ;
+C 185 ; WX 788 ; N a133 ; B 35 -14 754 705 ;
+C 186 ; WX 788 ; N a134 ; B 35 -14 754 705 ;
+C 187 ; WX 788 ; N a135 ; B 35 -14 754 705 ;
+C 188 ; WX 788 ; N a136 ; B 35 -14 754 705 ;
+C 189 ; WX 788 ; N a137 ; B 35 -14 754 705 ;
+C 190 ; WX 788 ; N a138 ; B 35 -14 754 705 ;
+C 191 ; WX 788 ; N a139 ; B 35 -14 754 705 ;
+C 192 ; WX 788 ; N a140 ; B 35 -14 754 705 ;
+C 193 ; WX 788 ; N a141 ; B 35 -14 754 705 ;
+C 194 ; WX 788 ; N a142 ; B 35 -14 754 705 ;
+C 195 ; WX 788 ; N a143 ; B 35 -14 754 705 ;
+C 196 ; WX 788 ; N a144 ; B 35 -14 754 705 ;
+C 197 ; WX 788 ; N a145 ; B 35 -14 754 705 ;
+C 198 ; WX 788 ; N a146 ; B 35 -14 754 705 ;
+C 199 ; WX 788 ; N a147 ; B 35 -14 754 705 ;
+C 200 ; WX 788 ; N a148 ; B 35 -14 754 705 ;
+C 201 ; WX 788 ; N a149 ; B 35 -14 754 705 ;
+C 202 ; WX 788 ; N a150 ; B 35 -14 754 705 ;
+C 203 ; WX 788 ; N a151 ; B 35 -14 754 705 ;
+C 204 ; WX 788 ; N a152 ; B 35 -14 754 705 ;
+C 205 ; WX 788 ; N a153 ; B 35 -14 754 705 ;
+C 206 ; WX 788 ; N a154 ; B 35 -14 754 705 ;
+C 207 ; WX 788 ; N a155 ; B 35 -14 754 705 ;
+C 208 ; WX 788 ; N a156 ; B 35 -14 754 705 ;
+C 209 ; WX 788 ; N a157 ; B 35 -14 754 705 ;
+C 210 ; WX 788 ; N a158 ; B 35 -14 754 705 ;
+C 211 ; WX 788 ; N a159 ; B 35 -14 754 705 ;
+C 212 ; WX 894 ; N a160 ; B 35 58 860 634 ;
+C 213 ; WX 838 ; N a161 ; B 35 152 803 540 ;
+C 214 ; WX 1016 ; N a163 ; B 34 152 981 540 ;
+C 215 ; WX 458 ; N a164 ; B 35 -127 422 820 ;
+C 216 ; WX 748 ; N a196 ; B 35 94 698 597 ;
+C 217 ; WX 924 ; N a165 ; B 35 140 890 552 ;
+C 218 ; WX 748 ; N a192 ; B 35 94 698 597 ;
+C 219 ; WX 918 ; N a166 ; B 35 166 884 526 ;
+C 220 ; WX 927 ; N a167 ; B 35 32 892 660 ;
+C 221 ; WX 928 ; N a168 ; B 35 129 891 562 ;
+C 222 ; WX 928 ; N a169 ; B 35 128 893 563 ;
+C 223 ; WX 834 ; N a170 ; B 35 155 799 537 ;
+C 224 ; WX 873 ; N a171 ; B 35 93 838 599 ;
+C 225 ; WX 828 ; N a172 ; B 35 104 791 588 ;
+C 226 ; WX 924 ; N a173 ; B 35 98 889 594 ;
+C 227 ; WX 924 ; N a162 ; B 35 98 889 594 ;
+C 228 ; WX 917 ; N a174 ; B 35 0 882 692 ;
+C 229 ; WX 930 ; N a175 ; B 35 84 896 608 ;
+C 230 ; WX 931 ; N a176 ; B 35 84 896 608 ;
+C 231 ; WX 463 ; N a177 ; B 35 -99 429 791 ;
+C 232 ; WX 883 ; N a178 ; B 35 71 848 623 ;
+C 233 ; WX 836 ; N a179 ; B 35 44 802 648 ;
+C 234 ; WX 836 ; N a193 ; B 35 44 802 648 ;
+C 235 ; WX 867 ; N a180 ; B 35 101 832 591 ;
+C 236 ; WX 867 ; N a199 ; B 35 101 832 591 ;
+C 237 ; WX 696 ; N a181 ; B 35 44 661 648 ;
+C 238 ; WX 696 ; N a200 ; B 35 44 661 648 ;
+C 239 ; WX 874 ; N a182 ; B 35 77 840 619 ;
+C 241 ; WX 874 ; N a201 ; B 35 73 840 615 ;
+C 242 ; WX 760 ; N a183 ; B 35 0 725 692 ;
+C 243 ; WX 946 ; N a184 ; B 35 160 911 533 ;
+C 244 ; WX 771 ; N a197 ; B 34 37 736 655 ;
+C 245 ; WX 865 ; N a185 ; B 35 207 830 481 ;
+C 246 ; WX 771 ; N a194 ; B 34 37 736 655 ;
+C 247 ; WX 888 ; N a198 ; B 34 -19 853 712 ;
+C 248 ; WX 967 ; N a186 ; B 35 124 932 568 ;
+C 249 ; WX 888 ; N a195 ; B 34 -19 853 712 ;
+C 250 ; WX 831 ; N a187 ; B 35 113 796 579 ;
+C 251 ; WX 873 ; N a188 ; B 36 118 838 578 ;
+C 252 ; WX 927 ; N a189 ; B 35 150 891 542 ;
+C 253 ; WX 970 ; N a190 ; B 35 76 931 616 ;
+C 254 ; WX 918 ; N a191 ; B 34 99 884 593 ;
+C -1 ; WX 410 ; N a86 ; B 35 0 375 692 ;
+C -1 ; WX 509 ; N a85 ; B 35 0 475 692 ;
+C -1 ; WX 334 ; N a95 ; B 35 0 299 692 ;
+C -1 ; WX 509 ; N a205 ; B 35 0 475 692 ;
+C -1 ; WX 390 ; N a89 ; B 35 -14 356 705 ;
+C -1 ; WX 234 ; N a87 ; B 35 -14 199 705 ;
+C -1 ; WX 276 ; N a91 ; B 35 0 242 692 ;
+C -1 ; WX 390 ; N a90 ; B 35 -14 355 705 ;
+C -1 ; WX 410 ; N a206 ; B 35 0 375 692 ;
+C -1 ; WX 317 ; N a94 ; B 35 0 283 692 ;
+C -1 ; WX 317 ; N a93 ; B 35 0 283 692 ;
+C -1 ; WX 276 ; N a92 ; B 35 0 242 692 ;
+C -1 ; WX 334 ; N a96 ; B 35 0 299 692 ;
+C -1 ; WX 234 ; N a88 ; B 35 -14 199 705 ;
+EndCharMetrics
+EndFontMetrics
+
\ No newline at end of file
diff --git a/tlt3.0/library/bltGraph.pro b/tlt3.0/library/bltGraph.pro
new file mode 100644
index 0000000..813d92a
--- /dev/null
+++ b/tlt3.0/library/bltGraph.pro
@@ -0,0 +1,472 @@
+
+%%BeginProlog
+%
+% PostScript prolog file of the BLT graph widget.
+%
+% Copyright 1989-1992 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.
+%
+% Copyright 1991-1997 Bell Labs Innovations for Lucent Technologies.
+%
+% 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 the
+% copyright notice and warranty disclaimer appear in supporting documentation,
+% and that the names of Lucent Technologies any of their entities not be used
+% in advertising or publicity pertaining to distribution of the software
+% without specific, written prior permission.
+%
+% Lucent Technologies disclaims all warranties with regard to this software,
+% including all implied warranties of merchantability and fitness. In no event
+% shall Lucent Technologies 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
+% tortuous action, arising out of or in connection with the use or performance
+% of this software.
+%
+
+200 dict begin
+
+/BaseRatio 1.3467736870885982 def % Ratio triangle base / symbol size
+/BgColorProc 0 def % Background color routine (symbols)
+/DrawSymbolProc 0 def % Routine to draw symbol outline/fill
+/StippleProc 0 def % Stipple routine (bar segments)
+/DashesProc 0 def % Dashes routine (line segments)
+
+% Define the array ISOLatin1Encoding (which specifies how characters are
+% encoded for ISO-8859-1 fonts), if it isn't already present (Postscript
+% level 2 is supposed to define it, but level 1 doesn't).
+
+systemdict /ISOLatin1Encoding known not {
+ /ISOLatin1Encoding [
+ /space /space /space /space /space /space /space /space
+ /space /space /space /space /space /space /space /space
+ /space /space /space /space /space /space /space /space
+ /space /space /space /space /space /space /space /space
+ /space /exclam /quotedbl /numbersign /dollar /percent /ampersand
+ /quoteright
+ /parenleft /parenright /asterisk /plus /comma /minus /period /slash
+ /zero /one /two /three /four /five /six /seven
+ /eight /nine /colon /semicolon /less /equal /greater /question
+ /at /A /B /C /D /E /F /G
+ /H /I /J /K /L /M /N /O
+ /P /Q /R /S /T /U /V /W
+ /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore
+ /quoteleft /a /b /c /d /e /f /g
+ /h /i /j /k /l /m /n /o
+ /p /q /r /s /t /u /v /w
+ /x /y /z /braceleft /bar /braceright /asciitilde /space
+ /space /space /space /space /space /space /space /space
+ /space /space /space /space /space /space /space /space
+ /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent
+ /dieresis /space /ring /cedilla /space /hungarumlaut /ogonek /caron
+ /space /exclamdown /cent /sterling /currency /yen /brokenbar /section
+ /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen
+ /registered /macron
+ /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph
+ /periodcentered
+ /cedillar /onesuperior /ordmasculine /guillemotright /onequarter
+ /onehalf /threequarters /questiondown
+ /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla
+ /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex
+ /Idieresis
+ /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply
+ /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn
+ /germandbls
+ /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla
+ /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex
+ /idieresis
+ /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide
+ /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn
+ /ydieresis
+ ] def
+} if
+
+% font ISOEncode font
+% This procedure changes the encoding of a font from the default
+% Postscript encoding to ISOLatin1. It is typically invoked just
+% before invoking "setfont". The body of this procedure comes from
+% Section 5.6.1 of the Postscript book.
+
+/ISOEncode {
+ dup length dict
+ begin
+ {1 index /FID ne {def} {pop pop} ifelse} forall
+ /Encoding ISOLatin1Encoding def
+ currentdict
+ end
+
+ % I'm not sure why it's necessary to use "definefont" on this new
+ % font, but it seems to be important; just use the name "Temporary"
+ % for the font.
+
+ /Temporary exch definefont
+} bind def
+
+/Stroke {
+ gsave
+ stroke
+ grestore
+} def
+
+/Fill {
+ gsave
+ fill
+ grestore
+} def
+
+/SetFont {
+ % Stack: pointSize fontName
+ findfont exch scalefont ISOEncode setfont
+} def
+
+/Box {
+ % Stack: x y width height
+ newpath
+ exch 4 2 roll moveto
+ dup 0 rlineto
+ exch 0 exch rlineto
+ neg 0 rlineto
+ closepath
+} def
+
+% The next two definitions are taken from "$tk_library/prolog.ps"
+
+% desiredSize EvenPixels closestSize
+%
+% The procedure below is used for stippling. Given the optimal size
+% of a dot in a stipple pattern in the current user coordinate system,
+% compute the closest size that is an exact multiple of the device's
+% pixel size. This allows stipple patterns to be displayed without
+% aliasing effects.
+
+/EvenPixels {
+ % Compute exact number of device pixels per stipple dot.
+ dup 0 matrix currentmatrix dtransform
+ dup mul exch dup mul add sqrt
+
+ % Round to an integer, make sure the number is at least 1, and compute
+ % user coord distance corresponding to this.
+ dup round dup 1 lt {pop 1} if
+ exch div mul
+} bind def
+
+% width height string filled StippleFill --
+%
+% Given a path and other graphics information already set up, this
+% procedure will fill the current path in a stippled fashion. "String"
+% contains a proper image description of the stipple pattern and
+% "width" and "height" give its dimensions. If "filled" is true then
+% it means that the area to be stippled is gotten by filling the
+% current path (e.g. the interior of a polygon); if it's false, the
+% area is gotten by stroking the current path (e.g. a wide line).
+% Each stipple dot is assumed to be about one unit across in the
+% current user coordinate system.
+
+% width height string StippleFill --
+%
+% Given a path already set up and a clipping region generated from
+% it, this procedure will fill the clipping region with a stipple
+% pattern. "String" contains a proper image description of the
+% stipple pattern and "width" and "height" give its dimensions. Each
+% stipple dot is assumed to be about one unit across in the current
+% user coordinate system. This procedure trashes the graphics state.
+
+/StippleFill {
+ % The following code is needed to work around a NeWSprint bug.
+
+ /tmpstip 1 index def
+
+ % Change the scaling so that one user unit in user coordinates
+ % corresponds to the size of one stipple dot.
+ 1 EvenPixels dup scale
+
+ % Compute the bounding box occupied by the path (which is now
+ % the clipping region), and round the lower coordinates down
+ % to the nearest starting point for the stipple pattern. Be
+ % careful about negative numbers, since the rounding works
+ % differently on them.
+
+ pathbbox
+ 4 2 roll
+ 5 index div dup 0 lt {1 sub} if cvi 5 index mul 4 1 roll
+ 6 index div dup 0 lt {1 sub} if cvi 6 index mul 3 2 roll
+
+ % Stack now: width height string y1 y2 x1 x2
+ % Below is a doubly-nested for loop to iterate across this area
+ % in units of the stipple pattern size, going up columns then
+ % across rows, blasting out a stipple-pattern-sized rectangle at
+ % each position
+
+ 6 index exch {
+ 2 index 5 index 3 index {
+ % Stack now: width height string y1 y2 x y
+
+ gsave
+ 1 index exch translate
+ 5 index 5 index true matrix tmpstip imagemask
+ grestore
+ } for
+ pop
+ } for
+ pop pop pop pop pop
+} bind def
+
+
+/LS { % Stack: x1 y1 x2 y2
+ newpath
+ 4 2 roll moveto
+ lineto
+ closepath
+ stroke
+} def
+
+/EndText {
+ %Stack :
+ grestore
+} def
+
+/BeginText {
+ %Stack : w h theta centerX centerY
+ gsave
+ % Translate the origin to the center of bounding box and rotate
+ translate neg rotate
+ % Translate back to the origin of the text region
+ -0.5 mul exch -0.5 mul exch translate
+} def
+
+/DrawAdjText {
+ %Stack : str strWidth x y
+ moveto % Go to the text position
+ exch dup dup 4 2 roll
+
+ % Adjust character widths to get desired overall string width
+ % adjust X = (desired width - real width)/#chars
+
+ stringwidth pop sub exch
+ length div
+ 0 3 -1 roll
+
+ % Flip back the scale so that the string is not drawn in reverse
+
+ gsave
+ 1 -1 scale
+ ashow
+ grestore
+} def
+
+/DrawBitmap {
+ % Stack: ?bgColorProc? boolean centerX centerY width height theta imageStr
+ gsave
+ 6 -2 roll translate % Translate to center of bounding box
+ 4 1 roll neg rotate % Rotate by theta
+
+ % Find upperleft corner of bounding box
+
+ 2 copy -.5 mul exch -.5 mul exch translate
+ 2 copy scale % Make pixel unit scale
+ newpath
+ 0 0 moveto
+ 0 1 lineto
+ 1 1 lineto
+ 1 0 lineto
+ closepath
+
+ % Fill rectangle with background color
+
+ 4 -1 roll {
+ gsave
+ 4 -1 roll exec fill
+ grestore
+ } if
+
+ % Paint the image string into the unit rectangle
+
+ 2 copy true 3 -1 roll 0 0 5 -1 roll 0 0 6 array astore 5 -1 roll
+ imagemask
+ grestore
+} def
+
+% Symbols:
+
+% Skinny-cross
+/Sc {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate 45 rotate
+ 0 0 3 -1 roll Sp
+ grestore
+} def
+
+% Skinny-plus
+/Sp {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate
+ 2 idiv
+ dup 2 copy
+ newpath
+ neg 0
+ moveto 0
+ lineto
+ DrawSymbolProc
+ newpath
+ neg 0
+ exch moveto 0
+ exch lineto
+ DrawSymbolProc
+ grestore
+} def
+
+% Cross
+/Cr {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate 45 rotate
+ 0 0 3 -1 roll Pl
+ grestore
+} def
+
+% Plus
+/Pl {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate
+ dup 2 idiv
+ exch 6 idiv
+
+ %
+ % 2 3 The plus/cross symbol is a
+ % closed polygon of 12 points.
+ % 0 1 4 5 The diagram to the left
+ % x,y represents the positions of
+ % 11 10 7 6 the points which are computed
+ % below.
+ % 9 8
+ %
+
+ newpath
+ 2 copy exch neg exch neg moveto
+ dup neg dup lineto
+ 2 copy neg exch neg lineto
+ 2 copy exch neg lineto
+ dup dup neg lineto
+ 2 copy neg lineto 2 copy lineto
+ dup dup lineto
+ 2 copy exch lineto
+ 2 copy neg exch lineto
+ dup dup neg exch lineto
+ exch neg exch lineto
+ closepath
+ DrawSymbolProc
+ grestore
+} def
+
+% Circle
+/Ci {
+ % Stack: x y symbolSize
+ gsave
+ 3 copy pop moveto
+ newpath
+ 2 div 0 360 arc
+ closepath
+ DrawSymbolProc
+ grestore
+} def
+
+% Square
+/Sq {
+ % Stack: x y symbolSize
+ gsave
+ dup dup 2 div dup
+ 6 -1 roll exch sub exch
+ 5 -1 roll exch sub 4 -2 roll Box
+ DrawSymbolProc
+ grestore
+} def
+
+% Line
+/Li {
+ % Stack: x y symbolSize
+ gsave
+ 3 1 roll exch 3 -1 roll 2 div 3 copy
+ newpath
+ sub exch moveto
+ add exch lineto
+ closepath
+ stroke
+ grestore
+} def
+
+% Diamond
+/Di {
+ % Stack: x y symbolSize
+ gsave
+ 3 1 roll translate 45 rotate 0 0 3 -1 roll Sq
+ grestore
+} def
+
+% Triangle
+/Tr {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate
+ BaseRatio mul 0.5 mul % Calculate 1/2 base
+ dup 0 exch 30 cos mul % h1 = height above center point
+ neg % b2 0 -h1
+ newpath
+ moveto % point 1; b2
+ dup 30 sin 30 cos div mul % h2 = height below center point
+ 2 copy lineto % point 2; b2 h2
+ exch neg exch lineto %
+ closepath
+ DrawSymbolProc
+ grestore
+} def
+
+% Arrow
+/Ar {
+ % Stack: x y symbolSize
+ gsave
+ 3 -2 roll translate
+ BaseRatio mul 0.5 mul % Calculate 1/2 base
+ dup 0 exch 30 cos mul % h1 = height above center point
+ % b2 0 h1
+ newpath moveto % point 1; b2
+ dup 30 sin 30 cos div mul % h2 = height below center point
+ neg % -h2 b2
+ 2 copy lineto % point 2; b2 h2
+ exch neg exch lineto %
+ closepath
+ DrawSymbolProc
+ grestore
+} def
+
+% Bitmap
+/Bm {
+ % Stack: x y symbolSize
+ gsave
+ 3 1 roll translate pop DrawSymbolProc
+ grestore
+} def
+
+%%EndProlog
+
+%%BeginSetup
+gsave % Save the graphics state
+
+% Default line/text style parameters
+
+1 setlinewidth % width
+1 setlinejoin % join
+0 setlinecap % cap
+[] 0 setdash % dashes
+
+0 0 0 setrgbcolor % color
+
diff --git a/tlt3.0/library/graph.tcl b/tlt3.0/library/graph.tcl
new file mode 100644
index 0000000..16c0e14
--- /dev/null
+++ b/tlt3.0/library/graph.tcl
@@ -0,0 +1,840 @@
+
+namespace eval ::blt::legend {
+ variable _private
+ array set _private {
+ afterId ""
+ scroll 0
+ space off
+ drag 0
+ x 0
+ y 0
+ }
+}
+
+namespace eval ::blt::ZoomStack {
+ variable _private
+ array set _private {
+ afterId ""
+ scroll 0
+ space off
+ drag 0
+ x 0
+ y 0
+ }
+}
+
+option add *zoomOutline.dashes 4
+option add *zoomOutline.lineWidth 2
+option add *zoomOutline.xor yes
+option add *zoomTitle.anchor nw
+option add *zoomTitle.coords "-Inf Inf"
+option add *zoomTitle.font "Arial 14"
+option add *zoomTitle.foreground yellow3
+option add *zoomTitle.shadow yellow4
+
+# ----------------------------------------------------------------------
+#
+# Initialize --
+#
+# Invoked by internally by Treeview_Init routine. Initializes
+# the default bindings for the treeview widget entries. These
+# are local to the widget, so they can't be set through the
+# widget's class bind tags.
+#
+# ----------------------------------------------------------------------
+proc blt::LegendSelections { w } {
+ if 0 {
+ #
+ # Active entry bindings
+ #
+ $w legend bind all <Enter> {
+ %W entry highlight current
+ }
+ $w legend bind all <Leave> {
+ %W entry highlight ""
+ }
+ }
+
+ #
+ # ButtonPress-1
+ #
+ # Performs the following operations:
+ #
+ # 1. Clears the previous selection.
+ # 2. Selects the current entry.
+ # 3. Sets the focus to this entry.
+ # 4. Scrolls the entry into view.
+ # 5. Sets the selection anchor to this entry, just in case
+ # this is "multiple" mode.
+ #
+
+ $w legend bind all <ButtonPress-1> {
+ blt::legend::SetSelectionAnchor %W current
+ set blt::legend::_private(scroll) 1
+ }
+
+ #
+ # B1-Motion
+ #
+ # For "multiple" mode only. Saves the current location of the
+ # pointer for auto-scrolling. Resets the selection mark.
+ #
+ $w legend bind all <B1-Motion> {
+ set blt::legend::_private(x) %x
+ set blt::legend::_private(y) %y
+ set elem [%W legend get @%x,%y]
+ if { $elem != "" } {
+ if { [%W legend cget -selectmode] == "multiple" } {
+ %W legend selection mark $elem
+ } else {
+ blt::legend::SetSelectionAnchor %W $elem
+ }
+ }
+ }
+
+ #
+ # ButtonRelease-1
+ #
+ # For "multiple" mode only.
+ #
+ $w legend bind all <ButtonRelease-1> {
+ if { [%W legend cget -selectmode] == "multiple" } {
+ %W legend selection anchor current
+ }
+ after cancel $blt::legend::_private(afterId)
+ set blt::legend::_private(scroll) 0
+ }
+
+ #
+ # Shift-ButtonPress-1
+ #
+ # For "multiple" mode only.
+ #
+
+ $w legend bind all <Shift-ButtonPress-1> {
+ if { [%W legend cget -selectmode] == "multiple" &&
+ [%W legend selection present] } {
+ if { [%W legend get anchor] == "" } {
+ %W legend selection anchor current
+ }
+ set elem [%W legend get anchor]
+ %W legend selection clearall
+ %W legend selection set $elem current
+ } else {
+ blt::legend::SetSelectionAnchor %W current
+ }
+ }
+ $w legend bind all <Shift-Double-ButtonPress-1> {
+ # do nothing
+ }
+ $w legend bind all <Shift-B1-Motion> {
+ # do nothing
+ }
+ $w legend bind all <Shift-ButtonRelease-1> {
+ after cancel $blt::legend::_private(afterId)
+ set blt::legend::_private(scroll) 0
+ }
+
+ #
+ # Control-ButtonPress-1
+ #
+ # For "multiple" mode only.
+ #
+ $w legend bind all <Control-ButtonPress-1> {
+ if { [%W legend cget -selectmode] == "multiple" } {
+ set elem [%W legend get current]
+ %W legend selection toggle $elem
+ %W legend selection anchor $elem
+ } else {
+ blt::legend::SetSelectionAnchor %W current
+ }
+ }
+ $w legend bind all <Control-Double-ButtonPress-1> {
+ # do nothing
+ }
+ $w legend bind all <Control-B1-Motion> {
+ # do nothing
+ }
+ $w legend bind all <Control-ButtonRelease-1> {
+ after cancel $blt::legend::_private(afterId)
+ set blt::legend::_private(scroll) 0
+ }
+
+ $w legend bind all <Control-Shift-ButtonPress-1> {
+ if { [%W legend cget -selectmode] == "multiple" &&
+ [%W legend selection present] } {
+ if { [%W legend get anchor] == "" } {
+ %W selection anchor current
+ }
+ if { [%W legend selection includes anchor] } {
+ %W legend selection set anchor current
+ } else {
+ %W legend selection clear anchor current
+ %W legend selection set current
+ }
+ } else {
+ blt::legend::SetSelectionAnchor %W current
+ }
+ }
+ $w legend bind all <Control-Shift-Double-ButtonPress-1> {
+ # do nothing
+ }
+ $w legend bind all <Control-Shift-B1-Motion> {
+ # do nothing
+ }
+ $w legend bind all <KeyPress-Up> {
+ blt::legend::MoveFocus %W previous.row
+ if { $blt::legend::_private(space) } {
+ %W legend selection toggle focus
+ }
+ }
+ $w legend bind all <KeyPress-Down> {
+ blt::legend::MoveFocus %W next.row
+ if { $blt::legend::_private(space) } {
+ %W legend selection toggle focus
+ }
+ }
+ $w legend bind all <KeyPress-Left> {
+ blt::legend::MoveFocus %W previous.column
+ if { $blt::legend::_private(space) } {
+ %W legend selection toggle focus
+ }
+ }
+ $w legend bind all <KeyPress-Right> {
+ blt::legend::MoveFocus %W next.column
+ if { $blt::legend::_private(space) } {
+ %W legend selection toggle focus
+ }
+ }
+ $w legend bind all <KeyPress-space> {
+ if { [%W legend cget -selectmode] == "single" } {
+ if { [%W legend selection includes focus] } {
+ %W legend selection clearall
+ } else {
+ %W legend selection clearall
+ %W legend selection set focus
+ }
+ } else {
+ %W legend selection toggle focus
+ }
+ set blt::legend::_private(space) on
+ }
+
+ $w legend bind all <KeyRelease-space> {
+ set blt::legend::_private(space) off
+ }
+ $w legend bind all <KeyPress-Return> {
+ blt::legend::MoveFocus %W focus
+ set blt::legend::_private(space) on
+ }
+ $w legend bind all <KeyRelease-Return> {
+ set blt::legend::_private(space) off
+ }
+ $w legend bind all <KeyPress-Home> {
+ blt::legend::MoveFocus %W first
+ }
+ $w legend bind all <KeyPress-End> {
+ blt::tv::MoveFocus %W last
+ }
+}
+
+proc blt::legend::SetSelectionAnchor { w tagOrId } {
+ set elem [$w legend get $tagOrId]
+ # If the anchor hasn't changed, don't do anything
+ if { $elem != [$w legend get anchor] } {
+ $w legend selection clearall
+ $w legend focus $elem
+ $w legend selection set $elem
+ $w legend selection anchor $elem
+ }
+}
+
+# ----------------------------------------------------------------------
+#
+# MoveFocus --
+#
+# Invoked by KeyPress bindings. Moves the active selection to
+# the entry <where>, which is an index such as "up", "down",
+# "prevsibling", "nextsibling", etc.
+#
+# ----------------------------------------------------------------------
+proc blt::legend::MoveFocus { w elem } {
+ catch {$w legend focus $elem} result
+ puts stderr "result=$result elem=$elem"
+ if { [$w legend cget -selectmode] == "single" } {
+ $w legend selection clearall
+ $w legend selection set focus
+ $w legend selection anchor focus
+ }
+}
+
+
+proc Blt_ActiveLegend { g } {
+ $g legend bind all <Enter> [list blt::ActivateLegend $g ]
+ $g legend bind all <Leave> [list blt::DeactivateLegend $g]
+ $g legend bind all <ButtonPress-1> [list blt::HighlightLegend $g]
+}
+
+proc Blt_Crosshairs { g } {
+ blt::Crosshairs $g
+}
+
+proc Blt_ResetCrosshairs { g state } {
+ blt::Crosshairs $g "Any-Motion" $state
+}
+
+proc Blt_ZoomStack { g args } {
+ array set params {
+ -mode click
+ }
+ array set params $args
+ if { $params(-mode) == "click" } {
+ blt::ZoomStack::ClickClick $g
+ } else {
+ blt::ZoomStack::ClickRelease $g
+ }
+}
+
+proc Blt_PrintKey { g } {
+ blt::PrintKey $g
+}
+
+proc Blt_ClosestPoint { g } {
+ blt::ClosestPoint $g
+}
+
+#
+# The following procedures that reside in the "blt" namespace are
+# supposed to be private.
+#
+
+proc blt::ActivateLegend { g } {
+ set elem [$g legend get current]
+ $g legend activate $elem
+}
+proc blt::DeactivateLegend { g } {
+ set elem [$g legend get current]
+ $g legend deactivate $elem
+}
+
+proc blt::HighlightLegend { g } {
+ set elem [$g legend get current]
+ if { $elem != "" } {
+ set relief [$g element cget $elem -legendrelief]
+ if { $relief == "flat" } {
+ $g element configure $elem -legendrelief raised
+ $g element activate $elem
+ } else {
+ $g element configure $elem -legendrelief flat
+ $g element deactivate $elem
+ }
+ }
+}
+
+proc blt::Crosshairs { g {event "Any-Motion"} {state "on"}} {
+ $g crosshairs $state
+ bind crosshairs-$g <$event> {
+ %W crosshairs configure -position @%x,%y
+ }
+ bind crosshairs-$g <Leave> {
+ %W crosshairs off
+ }
+ bind crosshairs-$g <Enter> {
+ %W crosshairs on
+ }
+ $g crosshairs configure -color red
+ if { $state == "on" } {
+ blt::AddBindTag $g crosshairs-$g
+ } elseif { $state == "off" } {
+ blt::RemoveBindTag $g crosshairs-$g
+ }
+}
+
+proc blt::PrintKey { g {event "Shift-ButtonRelease-3"} } {
+ bind print-$g <$event> { Blt_PostScriptDialog %W }
+ blt::AddBindTag $g print-$g
+}
+
+proc blt::ClosestPoint { g {event "Control-ButtonPress-2"} } {
+ bind closest-point-$g <$event> {
+ blt::FindElement %W %x %y
+ }
+ blt::AddBindTag $g closest-point-$g
+}
+
+proc blt::AddBindTag { widget tag } {
+ set oldTagList [bindtags $widget]
+ if { [lsearch $oldTagList $tag] < 0 } {
+ bindtags $widget [linsert $oldTagList 0 $tag]
+ }
+}
+
+proc blt::RemoveBindTag { widget tag } {
+ set oldTagList [bindtags $widget]
+ set index [lsearch $oldTagList $tag]
+ if { $index >= 0 } {
+ bindtags $widget [lreplace $oldTagList $index $index]
+ }
+}
+
+proc blt::FindElement { g x y } {
+ array set info [$g element closest $x $y -interpolate yes]
+ if { ![info exists info(name)] } {
+ beep
+ return
+ }
+ # --------------------------------------------------------------
+ # find(name) - element Id
+ # find(index) - index of closest point
+ # find(x) find(y) - coordinates of closest point
+ # or closest point on line segment.
+ # find(dist) - distance from sample coordinate
+ # --------------------------------------------------------------
+ set markerName "bltClosest_$info(name)"
+ catch { $g marker delete $markerName }
+ $g marker create text -coords { $info(x) $info(y) } \
+ -name $markerName \
+ -text "$info(name): $info(dist)\nindex $info(index)" \
+ -font "Arial 6" \
+ -anchor center -justify left \
+ -yoffset 0 -bg {}
+
+ set coords [$g invtransform $x $y]
+ set nx [lindex $coords 0]
+ set ny [lindex $coords 1]
+
+ $g marker create line -coords "$nx $ny $info(x) $info(y)" \
+ -name line.$markerName
+
+ blt::FlashPoint $g $info(name) $info(index) 10
+ blt::FlashPoint $g $info(name) [expr $info(index) + 1] 10
+}
+
+proc blt::FlashPoint { g name index count } {
+ if { $count & 1 } {
+ $g element deactivate $name
+ } else {
+ $g element activate $name $index
+ }
+ incr count -1
+ if { $count > 0 } {
+ after 200 blt::FlashPoint $g $name $index $count
+ update
+ } else {
+ eval $g marker delete [$g marker names "bltClosest_*"]
+ }
+}
+
+
+proc blt::ZoomStack::Init { g } {
+ variable _private
+ set _private($g,interval) 100
+ set _private($g,afterId) 0
+ set _private($g,A,x) {}
+ set _private($g,A,y) {}
+ set _private($g,B,x) {}
+ set _private($g,B,y) {}
+ set _private($g,stack) {}
+ set _private($g,corner) A
+}
+
+proc blt::ZoomStack::ClickClick { g {start "ButtonPress-1"} {reset "ButtonPress-3"} } {
+ variable _private
+
+ Init $g
+
+ bind zoom-$g <Enter> "focus %W"
+ bind zoom-$g <KeyPress-Escape> { blt::ZoomStack::Reset %W }
+ bind zoom-$g <${start}> { blt::ZoomStack::SetPoint %W %x %y }
+ bind zoom-$g <${reset}> {
+ if { [%W inside %x %y] } {
+ blt::ZoomStack::Reset %W
+ }
+ }
+ blt::AddBindTag $g zoom-$g
+}
+
+proc blt::ZoomStack::ClickRelease { g } {
+ variable _private
+
+ Init $g
+ bind zoom-$g <Enter> "focus %W"
+ bind zoom-$g <KeyPress-Escape> { blt::ZoomStack::Reset %W }
+ bind zoom-$g <ButtonPress-1> { blt::ZoomStack::DragStart %W %x %y }
+ bind zoom-$g <B1-Motion> { blt::ZoomStack::DragMotion %W %x %y }
+ bind zoom-$g <ButtonRelease-1> { blt::ZoomStack::DragFinish %W %x %y }
+ bind zoom-$g <ButtonPress-3> {
+ if { [%W inside %x %y] } {
+ blt::ZoomStack::Reset %W
+ }
+ }
+ blt::AddBindTag $g zoom-$g
+}
+
+proc blt::ZoomStack::GetCoords { g x y index } {
+ variable _private
+ if { [$g cget -invertxy] } {
+ set _private($g,$index,x) $y
+ set _private($g,$index,y) $x
+ } else {
+ set _private($g,$index,x) $x
+ set _private($g,$index,y) $y
+ }
+}
+
+proc blt::ZoomStack::MarkPoint { g index } {
+ variable _private
+
+ if { [llength [$g xaxis use]] > 0 } {
+ set x [$g xaxis invtransform $_private($g,$index,x)]
+ } else if { [llength [$g x2axis use]] > 0 } {
+ set x [$g x2axis invtransform $_private($g,$index,x)]
+ }
+ if { [llength [$g yaxis use]] > 0 } {
+ set y [$g yaxis invtransform $_private($g,$index,y)]
+ } else if { [llength [$g y2axis use]] > 0 } {
+ set y [$g y2axis invtransform $_private($g,$index,y)]
+ }
+ set marker "zoomText_$index"
+ set text [format "x=%.4g\ny=%.4g" $x $y]
+
+ if [$g marker exists $marker] {
+ $g marker configure $marker -coords { $x $y } -text $text
+ } else {
+ $g marker create text -coords { $x $y } -name $marker \
+ -font "mathmatica1 10" \
+ -text $text -anchor center -bg {} -justify left
+ }
+}
+
+proc blt::ZoomStack::DestroyTitle { g } {
+ variable _private
+
+ if { $_private($g,corner) == "A" } {
+ catch { $g marker delete "zoomTitle" }
+ }
+}
+
+proc blt::ZoomStack::Pop { g } {
+ variable _private
+
+ set zoomStack $_private($g,stack)
+ if { [llength $zoomStack] > 0 } {
+ set cmd [lindex $zoomStack 0]
+ set _private($g,stack) [lrange $zoomStack 1 end]
+ eval $cmd
+ TitleLast $g
+ update
+ after 2000 [list blt::ZoomStack::DestroyTitle $g]
+ } else {
+ catch { $g marker delete "zoomTitle" }
+ }
+}
+
+# Push the old axis limits on the stack and set the new ones
+
+proc blt::ZoomStack::Push { g } {
+ variable _private
+
+ eval $g marker delete [$g marker names "zoom*"]
+ if { [info exists _private($g,afterId)] } {
+ after cancel $_private($g,afterId)
+ }
+ set x1 $_private($g,A,x)
+ set y1 $_private($g,A,y)
+ set x2 $_private($g,B,x)
+ set y2 $_private($g,B,y)
+
+ if { ($x1 == $x2) || ($y1 == $y2) } {
+ # No delta, revert to start
+ return
+ }
+ set cmd {}
+ foreach axis [$g axis names] {
+ if { [$g axis cget $axis -hide] } {
+ continue
+ }
+ set min [$g axis cget $axis -min]
+ set max [$g axis cget $axis -max]
+ set logscale [$g axis cget $axis -logscale]
+ # Save the current scale (log or linear) so that we can restore it.
+ # This is for the case where the user changes to logscale while
+ # zooming. A previously pushed axis limit could be negative. It
+ # seems better for popping the zoom stack to restore a previous view
+ # (not convert the ranges).
+ set c [list $g axis configure $axis]
+ lappend c -min $min -max $max -logscale $logscale
+ append cmd "$c\n"
+ }
+
+ # This effectively pushes the command to reset the graph to the current
+ # zoom level onto the stack. This is useful if the new axis ranges are
+ # bad and we need to reset the zoom stack.
+ set _private($g,stack) [linsert $_private($g,stack) 0 $cmd]
+ foreach axis [$g axis names] {
+ if { [$g axis cget $axis -hide] } {
+ continue; # Don't set zoom on axes not displayed.
+ }
+ set type [$g axis type $axis]
+ if { $type == "x" } {
+ set min [$g axis invtransform $axis $x1]
+ set max [$g axis invtransform $axis $x2]
+ } elseif { $type == "y" } {
+ set min [$g axis invtransform $axis $y1]
+ set max [$g axis invtransform $axis $y2]
+ } else {
+ continue; # Axis is not bound to any margin.
+ }
+ if { ![SetAxisRanges $g $axis $min $max] } {
+ Pop $g
+ bell
+ return
+ }
+ }
+# blt::busy hold $g
+ update; # This "update" redraws the graph
+# blt::busy release $g
+}
+
+proc blt::ZoomStack::SetAxisRanges { g axis min max } {
+ if { $min > $max } {
+ set tmp $max; set max $min; set min $tmp
+ }
+ if { [catch { $g axis configure $axis -min $min -max $max }] != 0 } {
+ return 0
+ }
+ return 1
+}
+
+#
+# This routine terminates either an existing zoom, or pops back to
+# the previous zoom level (if no zoom is in progress).
+#
+proc blt::ZoomStack::Reset { g } {
+ variable _private
+
+ if { ![info exists _private($g,corner)] } {
+ Init $g
+ }
+ eval $g marker delete [$g marker names "zoom*"]
+
+ if { $_private($g,corner) == "A" } {
+ # Reset the whole axis
+ Pop $g
+ } else {
+ set _private($g,corner) A
+ blt::RemoveBindTag $g select-region-$g
+ }
+}
+
+proc blt::ZoomStack::TitleNext { g } {
+ variable _private
+
+ set level [expr [llength $_private($g,stack)] + 1]
+ if { [$g cget -invertxy] } {
+ set coords "Inf -Inf"
+ } else {
+ set coords "-Inf Inf"
+ }
+ $g marker create text -name "zoomTitle" -text "Zoom #$level" \
+ -coords $coords -bindtags "" -anchor nw
+}
+
+proc blt::ZoomStack::TitleLast { g } {
+ variable _private
+
+ set level [llength $_private($g,stack)]
+ if { $level > 0 } {
+ $g marker create text -name "zoomTitle" -anchor nw \
+ -text "Zoom #$level"
+ }
+}
+
+
+proc blt::ZoomStack::SetPoint { g x y } {
+ variable _private
+ if { ![info exists _private($g,corner)] } {
+ Init $g
+ }
+ GetCoords $g $x $y $_private($g,corner)
+ bind select-region-$g <Motion> {
+ blt::ZoomStack::GetCoords %W %x %y B
+ #blt::ZoomStack::MarkPoint $g B
+ blt::ZoomStack::Box %W
+ }
+ if { $_private($g,corner) == "A" } {
+ if { ![$g inside $x $y] } {
+ return
+ }
+ # First corner selected, start watching motion events
+
+ #MarkPoint $g A
+ TitleNext $g
+
+ blt::AddBindTag $g select-region-$g
+ set _private($g,corner) B
+ } else {
+ # Delete the modal binding
+ blt::RemoveBindTag $g select-region-$g
+ Push $g
+ set _private($g,corner) A
+ }
+}
+
+proc blt::ZoomStack::DragStart { g x y } {
+ variable _private
+ if { ![info exists _private($g,corner)] } {
+ Init $g
+ }
+ GetCoords $g $x $y A
+ if { ![$g inside $x $y] } {
+ return
+ }
+ set _private(drag) 1
+ TitleNext $g
+}
+
+proc blt::ZoomStack::DragMotion { g x y } {
+ variable _private
+
+ if { $_private(drag) } {
+ GetCoords $g $x $y B
+ set dx [expr abs($_private($g,B,x) - $_private($g,A,x))]
+ set dy [expr abs($_private($g,B,y) - $_private($g,A,y))]
+ Box $g
+ if { $dy > 10 && $dx > 10 } {
+ return 1
+ }
+ }
+ return 0
+}
+
+proc blt::ZoomStack::DragFinish { g x y } {
+ variable _private
+ if { [DragMotion $g $x $y] } {
+ Push $g
+ } else {
+ eval $g marker delete [$g marker names "zoom*"]
+ if { [info exists _private($g,afterId)] } {
+ after cancel $_private($g,afterId)
+ }
+ }
+ set _private(drag) 0
+}
+
+
+proc blt::ZoomStack::MarchingAnts { g offset } {
+ variable _private
+
+ incr offset
+ # wrap the counter after 2^16
+ set offset [expr $offset & 0xFFFF]
+ if { [$g marker exists zoomOutline] } {
+ $g marker configure zoomOutline -dashoffset $offset
+ set interval $_private($g,interval)
+ set id [after $interval [list blt::ZoomStack::MarchingAnts $g $offset]]
+ set _private($g,afterId) $id
+ }
+}
+
+proc blt::ZoomStack::Box { g } {
+ variable _private
+
+ if { $_private($g,A,x) > $_private($g,B,x) } {
+ set x1 [$g xaxis invtransform $_private($g,B,x)]
+ set y1 [$g yaxis invtransform $_private($g,B,y)]
+ set x2 [$g xaxis invtransform $_private($g,A,x)]
+ set y2 [$g yaxis invtransform $_private($g,A,y)]
+ } else {
+ set x1 [$g xaxis invtransform $_private($g,A,x)]
+ set y1 [$g yaxis invtransform $_private($g,A,y)]
+ set x2 [$g xaxis invtransform $_private($g,B,x)]
+ set y2 [$g yaxis invtransform $_private($g,B,y)]
+ }
+ set coords { $x1 $y1 $x2 $y1 $x2 $y2 $x1 $y2 $x1 $y1 }
+ if { [$g marker exists "zoomOutline"] } {
+ $g marker configure "zoomOutline" -coords $coords
+ } else {
+ set X [lindex [$g xaxis use] 0]
+ set Y [lindex [$g yaxis use] 0]
+ $g marker create line -coords $coords -name "zoomOutline" \
+ -mapx $X -mapy $Y
+ set interval $_private($g,interval)
+ set id [after $interval [list blt::ZoomStack::MarchingAnts $g 0]]
+ set _private($g,afterId) $id
+ }
+}
+
+
+proc Blt_PostScriptDialog { g } {
+ set top $g.top
+ toplevel $top
+
+ foreach var { center landscape maxpect preview decorations padx
+ pady paperwidth paperheight width height colormode } {
+ global $g.$var
+ set $g.$var [$g postscript cget -$var]
+ }
+ set row 1
+ set col 0
+ label $top.title -text "PostScript Options"
+ blt::table $top $top.title -cspan 7
+ foreach bool { center landscape maxpect preview decorations } {
+ set w $top.$bool-label
+ label $w -text "-$bool" -font "courier 12"
+ blt::table $top $row,$col $w -anchor e -pady { 2 0 } -padx { 0 4 }
+ set w $top.$bool-yes
+ global $g.$bool
+ radiobutton $w -text "yes" -variable $g.$bool -value 1
+ blt::table $top $row,$col+1 $w -anchor w
+ set w $top.$bool-no
+ radiobutton $w -text "no" -variable $g.$bool -value 0
+ blt::table $top $row,$col+2 $w -anchor w
+ incr row
+ }
+ label $top.modes -text "-colormode" -font "courier 12"
+ blt::table $top $row,0 $top.modes -anchor e -pady { 2 0 } -padx { 0 4 }
+ set col 1
+ foreach m { color greyscale } {
+ set w $top.$m
+ radiobutton $w -text $m -variable $g.colormode -value $m
+ blt::table $top $row,$col $w -anchor w
+ incr col
+ }
+ set row 1
+ frame $top.sep -width 2 -bd 1 -relief sunken
+ blt::table $top $row,3 $top.sep -fill y -rspan 6
+ set col 4
+ foreach value { padx pady paperwidth paperheight width height } {
+ set w $top.$value-label
+ label $w -text "-$value" -font "courier 12"
+ blt::table $top $row,$col $w -anchor e -pady { 2 0 } -padx { 0 4 }
+ set w $top.$value-entry
+ global $g.$value
+ entry $w -textvariable $g.$value -width 8
+ blt::table $top $row,$col+1 $w -cspan 2 -anchor w -padx 8
+ incr row
+ }
+ blt::table configure $top c3 -width .125i
+ button $top.cancel -text "Cancel" -command "destroy $top"
+ blt::table $top $row,0 $top.cancel -width 1i -pady 2 -cspan 3
+ button $top.reset -text "Reset" -command "destroy $top"
+ #blt::table $top $row,1 $top.reset -width 1i
+ button $top.print -text "Print" -command "blt::ResetPostScript $g"
+ blt::table $top $row,4 $top.print -width 1i -pady 2 -cspan 2
+}
+
+proc blt::ResetPostScript { g } {
+ foreach var { center landscape maxpect preview decorations padx
+ pady paperwidth paperheight width height colormode } {
+ global $g.$var
+ set old [$g postscript cget -$var]
+ if { [catch {$g postscript configure -$var [set $g.$var]}] != 0 } {
+ $g postscript configure -$var $old
+ set $g.$var $old
+ }
+ }
+ $g postscript output "out.ps"
+ puts stdout "wrote file \"out.ps\"."
+ flush stdout
+}
diff --git a/tlt3.0/pkgIndex.tcl.in b/tlt3.0/pkgIndex.tcl.in
new file mode 100755
index 0000000..d7566b4
--- /dev/null
+++ b/tlt3.0/pkgIndex.tcl.in
@@ -0,0 +1,5 @@
+#
+# Tcl package index file
+#
+package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \
+ [list load [file join $dir @PKG_LIB_FILE@] @PACKAGE_NAME@]
diff --git a/tlt3.0/tclconfig/ChangeLog b/tlt3.0/tclconfig/ChangeLog
new file mode 100644
index 0000000..ffda2bb
--- /dev/null
+++ b/tlt3.0/tclconfig/ChangeLog
@@ -0,0 +1,980 @@
+2013-07-04 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Bug [3324676]: AC_PROG_INSTALL incompat,
+ Bug [3606445]: Unneeded -DHAVE_NO_SEH=1 when not building on Windows
+
+2013-07-02 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Bug [32afa6e256]: dirent64 check is incorrect in tcl.m4
+ (thanks to Brian Griffin)
+
+2013-06-20 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Use X11/Xlib.h for checking where X11 can be found
+ in stead of X11/XIntrinsic.h. Suggested by Pietro Cerutti.
+
+2013-06-04 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Eliminate NO_VIZ macro as current
+ zlib uses HAVE_HIDDEN in stead. One more last-moment
+ fix for FreeBSD by Pietro Cerutti
+
+2013-05-19 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Fix for FreeBSD, and remove support for old
+ FreeBSD versions. Patch by Pietro Cerutti
+
+2013-03-12 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * unix/tcl.m4: Patch by Andrew Shadura, providing better support for
+ * three architectures they have in Debian.
+
+2012-08-07 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: Added "-DNDEBUG" to CFLAGS_DEFAULT
+ when building with --disable-symbols.
+
+2012-08-07 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: [Bug 3555058]: Checkin [30736d63f0] broke
+ CFLAGS_DEFAULT, LDFLAGS_DEFAULT
+
+2012-08-07 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS
+
+2012-08-07 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [Bug 3511806]: Checkin [30736d63f0] broke CFLAGS
+
+2012-07-25 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: My previous commit (2012-04-03) broke the ActiveTcl
+ build for AMD64, because of the quotes in "C:/<path>/AMD64/cl.exe".
+ It turns out that the AC_TRY_COMPILE macro cannot handle that.
+
+2012-07-22 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: Tidy: consistency, spelling, phrasing, whitespace.
+ No functional change.
+
+2012-04-03 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [Bug 3511806] Compiler checks too early
+ This change allows to build the cygwin and mingw32 ports of
+ Tcl/Tk extensions to build out-of-the-box using a native or
+ cross-compiler, e.g. on Cygwin, Linux or Darwin.
+
+2011-04-02 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * install-sh: Fix issue with library stripping in install-sh
+ (backported from kevin_walzer's patch from Tcl 8.6 trunk)
+
+2011-04-05 Andreas Kupries <andreask at activestate.com>
+
+ * tcl.m4: Applied patch by Jeff Lawson. Nicer error message when
+ tclConfig.sh was not found.
+
+2010-12-15 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * install-sh: Upgrade to newer install-sh and use it.
+ * tcl.m4:
+
+2010-12-14 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: Better building on OpenBSD.
+
+2010-12-14 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: when using gcc, don't try to determine Win64 SDK
+
+2010-12-12 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: Determine correctly a cross-compiler-windres
+
+2010-11-23 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: add some cross-compile support, borrowed from Tcl 8.6
+
+2010-09-16 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct HP-UX LDFLAGS (only used when building big shell)
+
+2010-09-14 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: add extra if check for .manifest file generation
+ Add notice about package name and version being built.
+
+2010-09-09 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [FREQ #3058486] TEA_LOAD_CONFIG doesn't set all BUILD_ vars
+ Slightly related: defining BUILD_$1 on all platforms - not only win -
+ allows the -fvisibility feature to be used in extensions as well, at
+ least if you compile against tcl >= 8.5.
+
+2010-08-26 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: ensure safe quoting for autoheader usage
+
+2010-08-19 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: add TEA_ADD_CLEANFILES macro to make adding cleanfiles
+ easier, and add *.exp to CLEANFILES Windows default.
+ (TEA_MAKE_LIB): Enhanced to check for MSVC that requires manifests
+ and auto-embed it into proj DLL via MAKE_SHARED_LIB. Also define
+ VC_MANIFEST_EMBED_DLL and VC_MANIFEST_EMBED_EXE that do the same
+ magic in case it is needed for extended TEA projects.
+
+2010-08-16 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Bump to TEA_VERSION 3.9 ***
+ If upgrading from TEA_VERSION 3.8, copy over tcl.m4, change
+ TEA_INIT to use 3.9 and reconfigure (ac-2.59+).
+ BUILD_${PACKAGE_NAME} will be auto-defined on Windows for
+ correct setting of TCL_STORAGE_CLASS.
+ TEA_LOAD_CONFIG users should remove the SHLIB_LD_LIBS setting done
+ in configure.in (LIBS will be automagically populated by
+ TEA_LOAD_CONFIG).
+ TEA_EXPORT_CONFIG has been added for ${pkg}Config.sh creators
+ SHLIB_LD_FLAGS was deprecated a while ago, remove it if it is
+ still in your Makefile.in.
+
+ * tcl.m4: add /usr/lib64 to set of auto-search dirs. [Bug 1230554]
+ Auto-define BUILD_$PACKAGE_NAME so users don't need to. This
+ needs to correspond with $pkg.h define magic for TCL_STORAGE_CLASS.
+ Auto-define CLEANFILES. Users can expand it.
+ (SHLIB_LD_LIBS): define to '${LIBS}' default and change it only if
+ necessary. Platforms not using this may simply not work or have
+ very funky linkers.
+ (TEA_LOAD_CONFIG): When loading config for another extension,
+ auto-add stub libraries found with TEA_ADD_LIBS. Eases
+ configure.in for modules like itk and img::*.
+ (TEA_EXPORT_CONFIG): Add standardized function for exporting a
+ ${pkg}Config.sh. See use by img::* and itcl.
+
+2010-08-12 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Bump to TEA_VERSION 3.8 ***
+ If upgrading from TEA_VERSION 3.7, copy over tcl.m4, change
+ TEA_INIT to use 3.8 and reconfigure (ac-2.59+).
+ No other changes should be necessary.
+
+ * tcl.m4: remove more vestigial bits from removed platforms.
+ Add back SCO_SV-3.2*.
+ Remove use of DL_LIBS and DL_OBJS and related baggage - these are
+ only needed by the core to support 'load'.
+ Allow for macosx in TEA_ADD_SOURCES.
+ Correct check for found_xincludes=no in TEA_PATH_UNIX_X.
+
+2010-08-11 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: remove the following old platform configurations:
+ UNIX_SV*|UnixWare-5*, SunOS-4.*, SINIX*5.4*, SCO_SV-3.2*<readded>,
+ OSF1-1.*, NEXTSTEP-*, NetBSD-1.*|FreeBSD-[[1-2]].*, MP-RAS-*,
+ IRIX-5.*, HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*, dgux*,
+ BSD/OS-2.1*|BSD/OS-3*
+ (AIX): drop AIX-pre4 support and use of ldAix, use -bexpall/-brtl
+
+2010-07-05 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [Patch #1055668] removal of exported internals from
+ tclInt.h (EXTERN macro)
+
+2010-04-14 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4 - Backport a lot of quoting fixes from tcl8.6/unix/tcl.m4
+ - Fix determination of CYGPATH for CYGWIN
+ With those fixes, itcl and tdbc compile fine with CYGWIN
+
+2010-04-06 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * install-sh [Bug 2982540] configure and install* script files
+ should always have LF
+
+2010-02-19 Stuart Cassoff <stwo at users.sourceforge.net>
+
+ * tcl.m4: Correct compiler/linker flags for threaded builds on
+ OpenBSD.
+
+2010-01-19 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: Detect CYGWIN variant: win32 or unix
+
+2010-01-03 Donal K. Fellows <dkf at users.sf.net>
+
+ * unix/tcl.m4 (TEA_CONFIG_CFLAGS): [Tcl Bug 1636685]: Use the
+ configuration for modern FreeBSD suggested by the FreeBSD porter.
+
+2009-10-22 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [Tcl Patch #2883533] tcl.m4 support for Haiku OS
+
+2009-04-27 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): harden the check to add _r to CC on
+ AIX with threads.
+
+2009-04-10 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): check for 64-bit TkAqua.
+
+2009-03-26 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tclconfig/tcl.m4: Adapt LDFLAGS and LD_SEARCH_FLAGS
+ together with SHLIB_LD definition to unbreak building on HPUX.
+
+2009-03-20 Andreas Kupries <andreask at activestate.com>
+
+ * tclconfig/tcl.m4: Changed SHLIB_LD definition to unbreak
+ building on HPUX.
+
+2009-03-16 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4(TEA_PUBLIC_TK_HEADERS): Look at ${TK_INCLUDE_SPEC}
+ (found in tkConfig.sh) when trying to guess where tk.h might be
+ [Patch 1960628].
+
+2009-03-11 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4: Allow ${SHLIB_SUFFIX} to be overridden at
+ configure-time [Patch 1960628]. Also fix some comment typos,
+ and an uninitialized variable bug-waiting-to-happen.
+
+2008-12-21 Jan Nijtmans <nijtmans at users.sf.net>
+
+ * tcl.m4: [Bug 2073255] Tcl_GetString(NULL) doesn't crash on HP-UX
+ (this bug report was for Tcl, but holds for TEA as well.)
+
+2008-12-20 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: sync with tdbc tcl.m4 changes
+ (SunOS-5.11): Sun cc SHLIB_LD: use LDFLAGS_DEFAULT instead of LDFLAGS
+
+2008-12-02 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Bump to TEA_VERSION 3.7 ***
+
+ * tcl.m4: in private header check, check for <plat>Port.h instead
+ of Int.h to ensure all private headers are available.
+
+2008-11-04 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): sync TEA_PRIVATE_TK_HEADERS handling of
+ Tk.framework PrivateHeaders with TEA_PRIVATE_TCL_HEADERS.
+
+2008-11-04 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_PATH_TCLCONFIG, TEA_PATH_TKCONFIG): exit with error
+ when tclConfig.sh cannot be found. [Bug #1997760]
+ (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): allow for
+ finding the headers installed in the public areas, e.g. a result of
+ make install-private-headers. [Bug #1631922]
+
+2008-08-12 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): link shlib with current and compatiblity version
+ flags; look for libX11.dylib when searching for X11 libraries.
+
+2008-06-12 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (SunOS-5.11): fix 64bit amd64 support with gcc & Sun cc.
+
+2008-03-27 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (SunOS-5.1x): fix 64bit support for Sun cc. [Bug 1921166]
+
+2008-02-01 Donal K. Fellows <donal.k.fellows at man.ac.uk>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): Updated to work at least in part with
+ more modern VC versions. Currently just made the linker flags more
+ flexible; more work may be needed.
+
+2007-10-26 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): add support for 64-bit X11.
+
+2007-10-23 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Tagged tea-3-branch to start TEA 4 development on HEAD ***
+
+2007-09-17 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4: use '${CC} -shared' instead of 'ld -Bshareable'
+ to build shared libraries on current NetBSDs [Bug 1749251].
+
+2007-09-15 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: replace all direct references to compiler by ${CC} to
+ enable CC overriding at configure & make time.
+ (SunOS-5.1x): replace direct use of '/usr/ccs/bin/ld' in SHLIB_LD by
+ 'cc' compiler driver.
+
+2007-08-08 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: check Ttk dir for Tk private headers (8.5).
+ Add some comments to other bits.
+
+2007-06-25 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): move where / is added.
+
+2007-06-13 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: fix --with-tkinclude alignment. [Bug 1506111]
+
+2007-06-06 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): fix 64bit arch removal in fat 32&64bit builds.
+
+2007-05-18 Donal K. Fellows <donal.k.fellows at man.ac.uk>
+
+ * tcl.m4: Added quoting so that paths with spaces cause fewer
+ problems.
+
+2007-03-07 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): s/CFLAGS/CPPFLAGS/ in -mmacosx-version-min check.
+
+2007-02-15 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct private header check to search in generic subdir
+
+2007-02-09 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Bump to TEA_VERSION 3.6 ***
+
+ * tcl.m4: correct -d to -f
+ (TEA_CONFIG_CFLAGS): SHLIB_SUFFIX is .so on HP ia64 [Bug 1615058]
+
+2007-02-08 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_PRIVATE_TCL_HEADERS, TEA_PRIVATE_TK_HEADERS): check
+ that the dirs actually have private headers. [Bug 1631922]
+
+2007-02-04 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: add caching to -pipe check.
+
+2007-01-25 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: integrate CPPFLAGS into CFLAGS as late as possible and
+ move (rather than duplicate) -isysroot flags from CFLAGS to CPPFLAGS to
+ avoid errors about multiple -isysroot flags from some older gcc builds.
+
+2006-01-19 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: ensure CPPFLAGS env var is used when set. [Bug 1586861]
+ (Darwin): add -isysroot and -mmacosx-version-min flags to CPPFLAGS when
+ present in CFLAGS to avoid discrepancies between what headers configure
+ sees during preprocessing tests and compiling tests.
+
+2006-12-19 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): --enable-64bit: verify linking with 64bit -arch flag
+ succeeds before enabling 64bit build.
+
+2006-12-16 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Linux): fix previous change to use makefile variable
+ LDFLAGS_DEFAULT instead of LDFLAGS in SHLIB_LD, to ensure linker
+ flags in sampleextension Makefile are picked up.
+
+2006-11-26 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Linux): --enable-64bit support. [Patch 1597389], [Bug 1230558]
+
+2006-08-18 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): add support for --enable-64bit on x86_64, for
+ universal builds including x86_64 and for use of -mmacosx-version-min
+ instead of MACOSX_DEPLOYMENT_TARGET. For Tk extensions, remove 64-bit
+ arch flags from CFLAGS like in the Tk configure, as neither TkAqua nor
+ TkX11 can be built for 64-bit at present.
+
+2006-03-28 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: []-quote AC_DEFUN functions.
+ (TEA_PATH_TKCONFIG): Fixed Windows-specific check for tkConfig.sh.
+ (TEA_MAKE_LIB): Prepend 'lib' for Windows-gcc configs.
+
+2006-03-07 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4: Set SHLIB_LD_FLAGS='${LIBS}' on NetBSD,
+ as per the other *BSD variants [Bug 1334613].
+
+2006-01-25 Jeff Hobbs <jeffh at ActiveState.com>
+
+ *** Bump to TEA version 3.5 ***
+
+ * tcl.m4: keep LD_SEARCH_FLAGS and CC_SEARCH_FLAGS synchronous
+ with core tcl.m4 meaning.
+
+2006-01-24 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): use makefile variable LDFLAGS_DEFAULT instead of
+ LDFLAGS in SHLIB_LD, to ensure linker flags in sampleextension Makefile
+ are picked up. [Bug 1403343]
+
+2006-01-23 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: add C:/Tcl/lib and C:/Progra~1/Tcl/lib dirs to check for
+ *Config.sh on Windows. [Bug 1407544]
+
+2006-01-23 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): for Tk extensions, remove -arch ppc64 from CFLAGS
+ like in the Tk configure, as neither TkAqua nor TkX11 can be built for
+ 64bit at present (no 64bit GUI libraries).
+
+2006-01-22 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: restore system=windows on Windows.
+ Remove error if 'ar' isn't found (it may not be on Windows).
+ Do not add -lxnet or define _XOPEN_SOURCE on HP-UX by default.
+ Ensure the C|LDFLAGS_DEFAULT gets the fully sub'd value at
+ configure time.
+
+2006-01-10 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: add caching, use AC_CACHE_CHECK instead of AC_CACHE_VAL
+ where possible, consistent message quoting, sync relevant
+ tcl/unix/tcl.m4 HEAD changes and gratuitous formatting differences
+ (notably sunc removal of support for for ancient BSD's, IRIX 4,
+ RISCos and Ultrix by kennykb), Darwin improvements to
+ TEA_LOAD_*CONFIG to make linking work against Tcl/Tk frameworks
+ installed in arbitrary location, change TEA_PROG_* search order
+ (look in *_BIN_DIR parents before *_PREFIX).
+
+2006-01-05 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: add dkf's system config refactor
+
+2006-01-04 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: remove extraneous ' that causes bash 3.1 to choke
+
+2005-12-19 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4 (TEA_PATH_TCLCONFIG &c): Look for tclConfig.sh &c
+ in ${libdir}, where they are installed by default [Patch #1377407].
+
+2005-12-05 Don Porter <dgp at users.sf.net>
+
+ * tcl.m4 (TEA_PUBLIC_*_HEADERS): Better support for finding
+ header files for uninstalled Tcl and Tk.
+
+2005-12-02 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correctly bump TEA_VERSION var to 3.4
+
+2005-12-01 Daniel Steffen <das at users.sourceforge.net>
+
+ * unix/tcl.m4 (Darwin): fixed error when MACOSX_DEPLOYMENT_TARGET unset
+
+2005-11-29 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: *** Bump to TEA version 3.4 ***
+ Add Windows x64 build support.
+ Remove TEA_PATH_NOSPACE and handle the problem with ""s where
+ necessary - the macro relied on TCLSH_PROG which didn't work for
+ cross-compiles.
+
+2005-11-27 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): add 64bit support, add CFLAGS to SHLIB_LD to
+ support passing -isysroot in env(CFLAGS) to configure (flag can't
+ be present twice, so can't be in both CFLAGS and LDFLAGS during
+ configure), don't use -prebind when deploying on 10.4.
+ (TEA_ENABLE_LANGINFO, TEA_TIME_HANDLER): add/fix caching.
+
+2005-10-30 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: fixed two tests for TEA_WINDOWINGSYSTEM = "aqua" that
+ should have been for `uname -s` = "Darwin" instead; added some
+ missing quoting.
+ (TEA_PROG_TCLSH, TEA_PROG_WISH): fix incorrect assumption that
+ install location of tclConfig.sh/tkConfig.sh allows to determine
+ the tclsh/wish install dir via ../bin. Indeed tcl/tk can be
+ configured with arbitrary --libdir and --bindir (independent of
+ prefix) and such a configuration is in fact standard with Darwin
+ framework builds. At least now also check ${TCL_PREFIX}/bin
+ resp. ${TK_PREFIX}/bin for presence of tclsh resp. wish (if tcl/tk
+ have been configured with arbitrary --bindir, this will still not
+ find them, for a general solution *Config.sh would need to contain
+ the values of bindir/libdir/includedir passed to configure).
+
+2005-10-07 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: Fix Solaris 5.10 check and Solaris AMD64 64-bit builds.
+
+2005-10-04 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_PRIVATE_TCL_HEADERS): add / to finish sed macro
+ (TEA_ENABLE_THREADS): don't check for pthread_attr_setstacksize func
+
+2005-09-13 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: *** Update to TEA version 3.3 ***
+ define TEA_WINDOWINGSYSTEM in TEA_LOAD_TKCONFIG.
+ Make --enable-threads the default (users can --disable-threads).
+ Improve AIX ${CC}_r fix to better check existing ${CC} value.
+ Do the appropriate evals to not require the *TOP_DIR_NATIVE vars
+ be set for extensions that use private headers.
+ Make aqua check for Xlib compat headers the same as win32.
+
+2005-07-26 Mo DeJong <mdejong at users.sourceforge.net>
+
+ * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH,
+ TEA_PROG_WISH, TEA_BUILD_WISH): Remove
+ TEA_BUILD_TCLSH and TEA_BUILD_WISH because
+ of complaints that it broke the build when
+ only an installed version of Tcl was available
+ at extension build time. The TEA_PROG_TCLSH and
+ TEA_PROG_WISH macros will no longer search the
+ path at all. The build tclsh or installed
+ tclsh shell will now be found by TEA_PROG_TCLSH.
+
+2005-07-24 Mo DeJong <mdejong at users.sourceforge.net>
+
+ * tcl.m4 (TEA_PROG_TCLSH, TEA_BUILD_TCLSH,
+ TEA_PROG_WISH, TEA_BUILD_WISH):
+ Split confused search for tclsh on PATH and
+ build and install locations into two macros.
+ TEA_PROG_TCLSH and TEA_PROG_WISH search the
+ system PATH for an installed tclsh or wish.
+ The TEA_BUILD_TCLSH and TEA_BUILD_WISH
+ macros determine the name of tclsh or
+ wish in the Tcl or Tk build directory even
+ if tclsh or wish has not yet been built.
+ [Tcl bug 1160114]
+ [Tcl patch 1244153]
+
+2005-06-23 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (TEA_PRIVATE_TK_HEADERS): add ${TK_SRC_DIR}/macosx to
+ TK_INCLUDES when building against TkAqua.
+
+ * tcl.m4 (TEA_PATH_X): fixed missing comma in AC_DEFINE
+
+ * tcl.m4: changes to better support framework builds of Tcl and Tk out
+ of the box: search framework install locations for *Config.sh, and if in
+ presence of a framework build, use the framework's Headers and
+ PrivateHeaders directories for public and private includes. [FR 947735]
+
+2005-06-18 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): add -headerpad_max_install_names to LDFLAGS to
+ ensure we can always relocate binaries with install_name_tool.
+
+2005-06-04 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (TEA_PATH_X): for TEA_WINDOWINGSYSTEM == aqua, check if xlib
+ compat headers are available in tkheaders location, otherwise add xlib
+ sourcedir to TK_XINCLUDES.
+
+2005-04-25 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4: added AC_DEFINE* descriptions (from core tcl.m4) to allow
+ use with autoheader.
+ (Darwin): added configure checks for recently added linker flags
+ -single_module and -search_paths_first to allow building with older
+ tools (and on Mac OS X 10.1), use -single_module in SHLIB_LD.
+ (TEA_MISSING_POSIX_HEADERS): added caching of dirent.h check.
+ (TEA_BUGGY_STRTOD): added caching (sync with core tcl.m4).
+
+2005-03-24 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_TCL_64BIT_FLAGS): use Tcl header defaults for wide
+ int type only on Windows when __int64 is detected as valid.
+
+2005-03-24 Don Porter <dgp at users.sf.net>
+
+ * README.txt: Update reference to "SC_* macros" to "TEA_* macros".
+ * tcl.m4: Incorporated recent improvements in SC_PATH_TCLCONFIG
+ and SC_PATH_TKCONFIG into TEA_PATH_TCLCONFIG and TEA_PATH_TKCONFIG.
+ Corrected search path in TEA_PATH_CONFIG and added
+ AC_SUBST($1_BIN_DIR) to TEA_LOAD_CONFIG so that packages that load
+ the configuration of another package can know where they loaded
+ it from.
+
+2005-03-18 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): correct 2005-03-17 change to have
+ variant LD_SEARCH_FLAGS for gcc and cc builds.
+
+ * tcl.m4 (TEA_PROG_TCLSH, TEA_PROG_WISH): correct x-compile check.
+
+2005-03-17 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: Correct gcc build and HP-UX-11.
+
+2005-02-08 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_ADD_LIBS): don't touch lib args starting with -.
+ (TEA_CONFIG_CFLAGS): only define _DLL for CE in shared build.
+ (TEA_MAKE_LIB): set RANLIB* to : on Windows (it's not needed).
+
+2005-02-01 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: redo of 2005-01-27 changes to correctly handle paths
+ with spaces. Win/CE and Win/64 builds now require a prebuilt
+ tclsh to handle conversion to short pathnames. This is done in
+ the new TEA_PATH_NOSPACE macro. For Win/CE|64, make CC just the
+ compiler and move the necessary includes to CFLAGS.
+ (TEA_CONFIG_CFLAGS): Add Solaris 64-bit gcc build support.
+ (TEA_PROG_TCLSH, TEA_PROG_WISH): Allow TCLSH_PROG and WISH_PROG to
+ be set in the env and prevent resetting.
+ (TEA_ADD_LIBS): On Windows using GCC (mingw), convert foo.lib
+ args to -lfoo, for use with mingw.
+ *** POTENTIAL INCOMPATABILITY ***
+ (TEA_CONFIG_CFLAGS): Fix AIX gcc builds to work out-of-box.
+ Bumped TEA to 3.2.
+
+2005-01-27 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: remove cygpath calls to support msys.
+ Update base CE build assumption to "420,ARMV4,ARM,Pocket PC 2003".
+ Make STLIB_LD use $LINKBIN -lib.
+
+2005-01-25 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (Darwin): fixed bug with static build linking to dynamic
+ library in /usr/lib etc instead of linking to static library earlier
+ in search path. [Tcl Bug 956908]
+ Removed obsolete references to Rhapsody.
+
+2004-12-29 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: Updates for VC7 compatibility, fixing CFLAGS and LDFLAGS
+ options, using better default -O levels. [Bug 1092952, 1091967]
+
+2004-12-29 Joe English <jenglish at users.sourceforge.net>
+
+ * tcl.m4: Do not use ${DBGX} suffix when building
+ shared libraries [patch #1081595, TIP #34]
+
+2004-09-07 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): support eVC4 Win/CE builds
+
+2004-08-10 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_INIT, TEA_PREFIX): update handling of exec_prefix to
+ work around subdir configures since autoconf only propagates the
+ prefix (not exec_prefix).
+
+2004-07-23 Daniel Steffen <das at users.sourceforge.net>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): Darwin section: brought inline with
+ Tcl 8.5 HEAD config, removed core specific & obsolete settings.
+
+2004-07-22 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_PATH_X): check in TK_DEFS for MAC_OSX_TK to see if
+ we are compiling on Aqua. Add TEA_WINDOWINGSYSTEM var that
+ reflects 'tk windowingsystem' value.
+
+2004-07-16 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_ENABLE_THREADS): force a threaded build when
+ building against a threaded core.
+ (CFLAGS_WARNING): Remove -Wconversion for gcc builds
+ (TEA_CONFIG_CFLAGS): Reorder configure.in for better 64-bit build
+ configuration, replacing EXTRA_CFLAGS with CFLAGS. [Bug #874058]
+ Update to latest Tcl 8.5 head config settings.
+ Call this TEA version 3.1.
+
+2004-04-29 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_TCL_64BIT_FLAGS): replace AC_TRY_RUN test with
+ AC_TRY_COMPILE for the long vs. long long check. (kenny)
+
+2004-04-26 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_TCL_64BIT_FLAGS): update against core tcl.m4 to
+ define TCL_WIDE_INT_IS_LONG if 'using long'.
+
+2004-03-19 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct Windows builds getting LDFLAGS info in MAKE_LIB
+
+2004-02-11 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct TCL_INCLUDES for private headers on Windows - it
+ doesn't need the eval.
+
+2004-02-10 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: don't require TK_INCLUDES and TCL_INCLUDES to have the
+ DIR_NATIVE vars defined when using private headers on unix.
+ Allow $... to TEA_ADD_SOURCES for constructs like
+ TEA_ADD_SOURCES([\$(WIN_OBJECTS)]), that allow the developer to
+ place more in the Makefile.in.
+ tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
+ CHECK on limits.h
+
+2003-12-10 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * Makefile.in: added TEA_ADD_LIBS, TEA_ADD_INCLUDES and
+ * configure: TEA_ADD_CFLAGS to configurable parameters with
+ * configure.in: PKG_* equivs in the Makefile. This allows the
+ * tclconfig/tcl.m4: user to worry less about actual magic VAR names.
+ Corrected Makefile.in to note that TEA_ADD_TCL_SOURCES requires
+ exact file names.
+
+2003-12-09 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: updated OpenBSD support based on [Patch #775246] (cassoff)
+
+2003-12-05 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * configure:
+ * configure.in:
+ * Makefile.in (VPATH): readd $(srcdir) to front of VPATH as the
+ first part of VPATH can get chopped off.
+ Change .c.$(OBJEXT) rule to .c. at OBJEXT@ to support more makes.
+ * tclconfig/tcl.m4: add TEA_ADD_STUB_SOURCES to support libstub
+ generation and TEA_ADD_TCL_SOURCES to replace RUNTIME_SOURCES as
+ the way the user specifies library files.
+
+2003-12-03 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * configure: Update of TEA spec to (hopefully) simplify
+ * configure.in: some aspects of TEA by making use of more
+ * Makefile.in: AC 2.5x features. Use PACKAGE_NAME (instead
+ * generic/tclsample.c: of PACKAGE) and PACKAGE_VERSION (instead of
+ * tclconfig/tcl.m4: VERSION) arguments to AC_INIT as the TEA
+ package name and version.
+ Provide a version argument to TEA_INIT - starting with 3.0.
+ Drop all use of interior shell substs that older makefiles didn't
+ like. Use PKG_* naming convention instead.
+ Move specification of source files and public headers into
+ configure.in with TEA_ADD_SOURCES and TEA_ADD_HEADERS. These will
+ be munged during ./configure into the right obj file names (no
+ $(SOURCES:.c=.obj) needed).
+ There is almost nothing that should be touched in Makefile.in now
+ for the developer. May want to add a TEA_ADD_TCL_SOURCES for the
+ RUNTIME_SOURCES that remains.
+ Use SHLID_LD_FLAGS (instead of SHLID_LDFLAGS) as Tcl does.
+ Only specify the user requested LDFLAGS/CFLAGS in the Makefile,
+ don't mention the _OPTIMIZE/_DEBUG variants.
+
+2003-10-15 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: create a TEA_SETUP_COMPILER_CC the precedes the
+ TEA_SETUP_COMPILER macro. They are split so the check for CC
+ occurs before any use of CC. Also add AC_PROG_CPP to the compiler
+ checks.
+
+2003-10-06 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: Updated for autoconf 2.5x prereq.
+ Where TCL_WIDE_INT_TYPE would be __int64, defer to the code checks
+ in tcl.h, which also handles TCL_LL_MODIFIER* properly.
+
+2003-04-22 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct default setting of ARCH for WinCE builds.
+ Correct \ escaping for CE sed macros.
+
+2003-04-10 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: replace $(syscal) construct with older `syscall` for
+ systems where sh != bash.
+
+2003-04-09 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_WITH_CELIB): add --enable-wince and --with-celib
+ options for Windows/CE compilation support. Requires the
+ Microsoft eMbedded SDK and Keuchel's celib emulation layer.
+
+2003-02-18 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_ENABLE_THREADS): Make sure -lpthread gets passed on
+ the link line when checking for the pthread_attr_setstacksize
+ symbol. (dejong)
+
+ * tcl.m4 (TEA_SETUP_COMPILER): added default calls to
+ TEA_TCL_EARLY_FLAGS, TEA_TCL_64BIT_FLAGS,
+ TEA_MISSING_POSIX_HEADERS and TEA_BUGGY_STRTOD.
+
+2003-02-14 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: correct HP-UX ia64 --enable-64bit build flags
+
+2003-01-29 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: check $prefix/lib as well as $exec_prefix/lib when
+ looking for tcl|tkConfig.sh, as this check is done before we would
+ set exec_prefix when the user does not define it.
+
+2003-01-21 Mo DeJong <mdejong at users.sourceforge.net>
+
+ * tcl.m4 (TEA_CONFIG_CFLAGS): Fix build support
+ for mingw, the previous implementation would
+ use VC++ when compiling with mingw gcc. Don't
+ pass -fPIC since gcc always compiles pic code
+ under win32. Change some hard coded cases
+ of gcc to ${CC}.
+
+2002-10-15 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: move the CFLAGS definition from TEA_ENABLE_SHARED to
+ TEA_MAKE_LIB because setting too early confuses other AC_* macros.
+ Correct the HP-11 SHLIB_LD_LIBS setting.
+
+ * tcl.m4: add the CFLAGS definition into TEA_ENABLE_SHARED and
+ make it pick up the env CFLAGS at configure time.
+
+2002-10-09 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: add --enable-symbols=mem option to enable TCL_MEM_DEBUG.
+ Improved AIX 64-bit build support, allow it on AIX-4 as well.
+ Enable 64-bit HP-11 compilation with gcc.
+ Enable 64-bit IRIX64-6 cc build support.
+ Correct FreeBSD thread library linkage.
+ Add OSF1 static build support.
+ Improve SunOS-5 shared build SHLIB_LD macro.
+
+2002-07-20 Zoran Vasiljevic <zoran at archiware.com>
+
+ * tcl.m4: Added MINGW32 to list of systems checked for Windows build.
+ Also, fixes some indentation issues with "--with-XXX" options.
+
+2002-04-23 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_ENABLE_THREADS): added USE_THREAD_ALLOC define to
+ use new threaded allocatory by default on Unix for Tcl 8.4.
+ (TEA_CONFIG_CFLAGS): corrected LD_SEARCH_FLAGS for FreeBSD-3+.
+
+2002-04-22 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4 (TEA_SETUP_COMPILER): removed call to AC_CYGWIN so that
+ we can use autoconf 2.5x as well as 2.13. This prevents us from
+ being able to warn against the use of cygwin gcc at configure
+ time, but allows autoconf 2.5x, which is what is shipped with most
+ newer systems.
+
+2002-04-11 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: Enabled COFF as well as CV style debug info with
+ --enable-symbols to allow Dr. Watson users to see function info.
+ More info on debugging levels can be obtained at:
+ http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+
+2002-04-03 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: change all SC_* macros to TEA_*. The SC_ was for
+ Scriptics, which is no more. TEA represents a better, independent
+ prefix that won't need changing.
+ Added preliminary mingw gcc support. [Patch #538772]
+ Added TEA_PREFIX macro that handles defaulting the prefix and
+ exec_prefix vars to those used by Tcl if none were specified.
+ Added TEA_SETUP_COMPILER macro that encompasses the AC_PROG_CC
+ check and several other basic AC_PROG checks needed for making
+ executables. This greatly simplifies user's configure.in files.
+ Collapsed AIX-5 defines into AIX-* with extra checks for doing the
+ ELF stuff on AIX-5-ia64.
+ Updated TEA_ENABLE_THREADS to take an optional arg to allow
+ switching it on by default (for Thread) and add sanity checking to
+ warn the user if configuring threads incompatibly.
+
+2002-03-29 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: made sure that SHLIB_LDFLAGS was set to LDFLAGS_DEFAULT.
+ Removed --enable-64bit support for AIX-4 because it wasn't correct.
+ Added -MT or -MD Windows linker switches to properly support
+ symbols-enabled builds.
+
+2002-03-28 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: called AC_MSG_ERROR when SC_TEA_INIT wasn't called first
+ instead of calling it as that inlines it each time in shell code.
+ Changed Windows CFLAGS_OPTIMIZE to use -O2 instead of -Oti.
+ Noted TCL_LIB_VERSIONS_OK=nodots for Windows builds.
+ A few changes to support itcl (and perhaps others):
+ Added support for making your own stub libraries to SC_MAKE_LIB.
+ New SC_PATH_CONFIG and SC_LOAD_CONFIG that take a package name arg
+ and find that ${pkg}Config.sh file. itk uses this for itcl.
+
+2002-03-27 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: made SC_LOAD_TKCONFIG recognize when working with a Tk
+ build dir setup.
+ Added EXTRA_CFLAGS and SHLIB_LD_LIBS substs to SC_CONFIG_CFLAGS.
+ Added XLIBSW onto LIBS when it is defined.
+ Remove TCL_LIBS from MAKE_LIB and correctly use SHLIB_LD_LIBS
+ instead to not rely as much on tclConfig.sh cached info.
+ Add TK_BIN_DIR to paths to find wish in SC_PROG_WISH.
+ These move towards making TEA much more independent of *Config.sh.
+
+2002-03-19 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: corrected forgotten (UN)SHARED_LIB_SUFFIX and
+ SHLIB_SUFFIX defines for Win.
+ (SC_PATH_X): made this only do the check on unix platforms.
+
+2002-03-12 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * README.txt: updated to reflect fewer files
+
+2002-03-06 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * config.guess (removed):
+ * config.sub (removed): removed unnecessary files
+
+ * installFile.tcl (removed):
+ * mkinstalldirs (removed): these aren't really necessary for
+ making TEA work
+
+ * tcl.m4 (SC_PUBLIC_TCL_HEADERS, SC_PUBLIC_TK_HEADERS): don't
+ check /usr(/local)/include for includes on Windows when not using
+ gcc
+
+2002-03-05 Jeff Hobbs <jeffh at ActiveState.com>
+
+ * tcl.m4: added warnings on Windows, removed RELPATH define and
+ added TCL_LIBS to MAKE_LIB macro.
+
+ This import represents 2.0.0, or a new start at attempting to
+ make TEA much easier for C extension developers.
+
+ **** moved from tclpro project to core tcl project, ****
+ **** renamed to 'tclconfig' ****
+
+2001-03-15 Karl Lehenbauer <karl at procplace.com>
+
+ * installFile.tcl: Added updating of the modification time of
+ the target file whether we overwrote it or decided that it
+ hadn't changed. This was necessary for us to be able to
+ determine whether or not a module install touched the file.
+
+2001-03-08 Karl Lehenbauer <karl at procplace.com>
+
+ * installFile.tcl: Added support for converting new-style (1.1+)
+ Cygnus drive paths to Tcl-style.
+
+2001-01-15 <brent.welch at interwoven.com>
+
+ * tcl.m4: Added FreeBSD clause.
+
+2001-01-03 <brent.welch at interwoven.com>
+
+ * tcl.m4: Fixed typo in SC_LIB_SPEC where it is checking
+ for exec-prefix.
+
+2000-12-01 <brent.welch at interwoven.com>
+
+ * tcl.m4: Concatenated most of the Ajuba acsite.m4 file
+ so we don't need to modify the autoconf installation.
+ * config.guess:
+ * config.sub:
+ * installFile.tcl:
+ Added files from the itcl config subdirectory,
+ which should go away.
+
+2000-7-29 <welch at ajubasolutions.com>
+
+ * Fixed the use of TCL_SRC_DIR and TK_SRC_DIR within
+ TCL_PRIVATE_INCLUDES and TK_PRIVATE_INCLUDES to match their recent
+ change from $(srcdir) to $(srcdir)/..
diff --git a/tlt3.0/tclconfig/README.txt b/tlt3.0/tclconfig/README.txt
new file mode 100644
index 0000000..59b5a3e
--- /dev/null
+++ b/tlt3.0/tclconfig/README.txt
@@ -0,0 +1,26 @@
+These files comprise the basic building blocks for a Tcl Extension
+Architecture (TEA) extension. For more information on TEA see:
+
+ http://www.tcl.tk/doc/tea/
+
+This package is part of the Tcl project at SourceForge, and latest
+sources should be available there:
+
+ http://tcl.sourceforge.net/
+
+This package is a freely available open source package. You can do
+virtually anything you like with it, such as modifying it, redistributing
+it, and selling it either in whole or in part.
+
+CONTENTS
+========
+The following is a short description of the files you will find in
+the sample extension.
+
+README.txt This file
+
+install-sh Program used for copying binaries and script files
+ to their install locations.
+
+tcl.m4 Collection of Tcl autoconf macros. Included by a package's
+ aclocal.m4 to define TEA_* macros.
diff --git a/tlt3.0/tclconfig/install-sh b/tlt3.0/tclconfig/install-sh
new file mode 100755
index 0000000..7c34c3f
--- /dev/null
+++ b/tlt3.0/tclconfig/install-sh
@@ -0,0 +1,528 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2011-04-20.01; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# 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.
+
+nl='
+'
+IFS=" "" $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+ doit_exec=exec
+else
+ doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+ test "$posix_glob" != "?" || {
+ if (set -f) 2>/dev/null; then
+ posix_glob=
+ else
+ posix_glob=:
+ fi
+ }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+ or: $0 [OPTION]... SRCFILES... DIRECTORY
+ or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+ or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+ --help display this help and exit.
+ --version display version info and exit.
+
+ -c (ignored)
+ -C install only if different (preserve the last data modification time)
+ -d create directories instead of installing files.
+ -g GROUP $chgrpprog installed files to GROUP.
+ -m MODE $chmodprog installed files to MODE.
+ -o USER $chownprog installed files to USER.
+ -s $stripprog installed files.
+ -S $stripprog installed files.
+ -t DIRECTORY install into DIRECTORY.
+ -T report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+ CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+ RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+ case $1 in
+ -c) ;;
+
+ -C) copy_on_change=true;;
+
+ -d) dir_arg=true;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift;;
+
+ --help) echo "$usage"; exit $?;;
+
+ -m) mode=$2
+ case $mode in
+ *' '* | *' '* | *'
+'* | *'*'* | *'?'* | *'['*)
+ echo "$0: invalid mode: $mode" >&2
+ exit 1;;
+ esac
+ shift;;
+
+ -o) chowncmd="$chownprog $2"
+ shift;;
+
+ -s) stripcmd=$stripprog;;
+
+ -S) stripcmd="$stripprog $2"
+ shift;;
+
+ -t) dst_arg=$2
+ shift;;
+
+ -T) no_target_directory=true;;
+
+ --version) echo "$0 $scriptversion"; exit $?;;
+
+ --) shift
+ break;;
+
+ -*) echo "$0: invalid option: $1" >&2
+ exit 1;;
+
+ *) break;;
+ esac
+ shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+ # When -d is used, all remaining arguments are directories to create.
+ # When -t is used, the destination is already specified.
+ # Otherwise, the last argument is the destination. Remove it from $@.
+ for arg
+ do
+ if test -n "$dst_arg"; then
+ # $@ is not empty: it contains at least $arg.
+ set fnord "$@" "$dst_arg"
+ shift # fnord
+ fi
+ shift # arg
+ dst_arg=$arg
+ done
+fi
+
+if test $# -eq 0; then
+ if test -z "$dir_arg"; then
+ echo "$0: no input file specified." >&2
+ exit 1
+ fi
+ # It's OK to call `install-sh -d' without argument.
+ # This can happen when creating conditional directories.
+ exit 0
+fi
+
+if test -z "$dir_arg"; then
+ do_exit='(exit $ret); exit $ret'
+ trap "ret=129; $do_exit" 1
+ trap "ret=130; $do_exit" 2
+ trap "ret=141; $do_exit" 13
+ trap "ret=143; $do_exit" 15
+
+ # Set umask so as not to create temps with too-generous modes.
+ # However, 'strip' requires both read and write access to temps.
+ case $mode in
+ # Optimize common cases.
+ *644) cp_umask=133;;
+ *755) cp_umask=22;;
+
+ *[0-7])
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw='% 200'
+ fi
+ cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+ *)
+ if test -z "$stripcmd"; then
+ u_plus_rw=
+ else
+ u_plus_rw=,u+rw
+ fi
+ cp_umask=$mode$u_plus_rw;;
+ esac
+fi
+
+for src
+do
+ # Protect names starting with `-'.
+ case $src in
+ -*) src=./$src;;
+ esac
+
+ if test -n "$dir_arg"; then
+ dst=$src
+ dstdir=$dst
+ test -d "$dstdir"
+ dstdir_status=$?
+ else
+
+ # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+ # might cause directories to be created, which would be especially bad
+ # if $src (and thus $dsttmp) contains '*'.
+ if test ! -f "$src" && test ! -d "$src"; then
+ echo "$0: $src does not exist." >&2
+ exit 1
+ fi
+
+ if test -z "$dst_arg"; then
+ echo "$0: no destination specified." >&2
+ exit 1
+ fi
+
+ dst=$dst_arg
+ # Protect names starting with `-'.
+ case $dst in
+ -*) dst=./$dst;;
+ esac
+
+ # If destination is a directory, append the input filename; won't work
+ # if double slashes aren't ignored.
+ if test -d "$dst"; then
+ if test -n "$no_target_directory"; then
+ echo "$0: $dst_arg: Is a directory" >&2
+ exit 1
+ fi
+ dstdir=$dst
+ dst=$dstdir/`basename "$src"`
+ dstdir_status=0
+ else
+ # Prefer dirname, but fall back on a substitute if dirname fails.
+ dstdir=`
+ (dirname "$dst") 2>/dev/null ||
+ expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$dst" : 'X\(//\)[^/]' \| \
+ X"$dst" : 'X\(//\)$' \| \
+ X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+ echo X"$dst" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'
+ `
+
+ test -d "$dstdir"
+ dstdir_status=$?
+ fi
+ fi
+
+ obsolete_mkdir_used=false
+
+ if test $dstdir_status != 0; then
+ case $posix_mkdir in
+ '')
+ # Create intermediate dirs using mode 755 as modified by the umask.
+ # This is like FreeBSD 'install' as of 1997-10-28.
+ umask=`umask`
+ case $stripcmd.$umask in
+ # Optimize common cases.
+ *[2367][2367]) mkdir_umask=$umask;;
+ .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+ *[0-7])
+ mkdir_umask=`expr $umask + 22 \
+ - $umask % 100 % 40 + $umask % 20 \
+ - $umask % 10 % 4 + $umask % 2
+ `;;
+ *) mkdir_umask=$umask,go-w;;
+ esac
+
+ # With -d, create the new directory with the user-specified mode.
+ # Otherwise, rely on $mkdir_umask.
+ if test -n "$dir_arg"; then
+ mkdir_mode=-m$mode
+ else
+ mkdir_mode=
+ fi
+
+ posix_mkdir=false
+ case $umask in
+ *[123567][0-7][0-7])
+ # POSIX mkdir -p sets u+wx bits regardless of umask, which
+ # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+ ;;
+ *)
+ tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+ if (umask $mkdir_umask &&
+ exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+ then
+ if test -z "$dir_arg" || {
+ # Check for POSIX incompatibilities with -m.
+ # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+ # other-writeable bit of parent directory when it shouldn't.
+ # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+ ls_ld_tmpdir=`ls -ld "$tmpdir"`
+ case $ls_ld_tmpdir in
+ d????-?r-*) different_mode=700;;
+ d????-?--*) different_mode=755;;
+ *) false;;
+ esac &&
+ $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+ ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+ test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+ }
+ }
+ then posix_mkdir=:
+ fi
+ rmdir "$tmpdir/d" "$tmpdir"
+ else
+ # Remove any dirs left behind by ancient mkdir implementations.
+ rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+ fi
+ trap '' 0;;
+ esac;;
+ esac
+
+ if
+ $posix_mkdir && (
+ umask $mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+ )
+ then :
+ else
+
+ # The umask is ridiculous, or mkdir does not conform to POSIX,
+ # or it failed possibly due to a race condition. Create the
+ # directory the slow way, step by step, checking for races as we go.
+
+ case $dstdir in
+ /*) prefix='/';;
+ -*) prefix='./';;
+ *) prefix='';;
+ esac
+
+ eval "$initialize_posix_glob"
+
+ oIFS=$IFS
+ IFS=/
+ $posix_glob set -f
+ set fnord $dstdir
+ shift
+ $posix_glob set +f
+ IFS=$oIFS
+
+ prefixes=
+
+ for d
+ do
+ test -z "$d" && continue
+
+ prefix=$prefix$d
+ if test -d "$prefix"; then
+ prefixes=
+ else
+ if $posix_mkdir; then
+ (umask=$mkdir_umask &&
+ $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+ # Don't fail if two instances are running concurrently.
+ test -d "$prefix" || exit 1
+ else
+ case $prefix in
+ *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) qprefix=$prefix;;
+ esac
+ prefixes="$prefixes '$qprefix'"
+ fi
+ fi
+ prefix=$prefix/
+ done
+
+ if test -n "$prefixes"; then
+ # Don't fail if two instances are running concurrently.
+ (umask $mkdir_umask &&
+ eval "\$doit_exec \$mkdirprog $prefixes") ||
+ test -d "$dstdir" || exit 1
+ obsolete_mkdir_used=true
+ fi
+ fi
+ fi
+
+ if test -n "$dir_arg"; then
+ { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+ { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+ else
+
+ # Make a couple of temp file names in the proper directory.
+ dsttmp=$dstdir/_inst.$$_
+ rmtmp=$dstdir/_rm.$$_
+
+ # Trap to clean up those temp files at exit.
+ trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+ # Copy the file name to the temp name.
+ (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+ # 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 $cpprog $src $dsttmp" command.
+ #
+ { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+ { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+ { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+ { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+ # If -C, don't bother to copy if it wouldn't change the file.
+ if $copy_on_change &&
+ old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
+ new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+ eval "$initialize_posix_glob" &&
+ $posix_glob set -f &&
+ set X $old && old=:$2:$4:$5:$6 &&
+ set X $new && new=:$2:$4:$5:$6 &&
+ $posix_glob set +f &&
+
+ test "$old" = "$new" &&
+ $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+ then
+ rm -f "$dsttmp"
+ else
+ # Rename the file to the real destination.
+ $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+ # The rename failed, perhaps because mv can't rename something else
+ # to itself, or perhaps because mv is so ancient that it does not
+ # support -f.
+ {
+ # Now remove or move aside any old file at destination location.
+ # We try this two ways since rm can't unlink itself on some
+ # systems and the destination file might be busy for other
+ # reasons. In this case, the final cleanup might fail but the new
+ # file should still install successfully.
+ {
+ test ! -f "$dst" ||
+ $doit $rmcmd -f "$dst" 2>/dev/null ||
+ { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+ { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+ } ||
+ { echo "$0: cannot unlink or rename $dst" >&2
+ (exit 1); exit 1
+ }
+ } &&
+
+ # Now rename the file to the real destination.
+ $doit $mvcmd "$dsttmp" "$dst"
+ }
+ fi || exit 1
+
+ trap '' 0
+ fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/tlt3.0/tclconfig/tcl.m4 b/tlt3.0/tclconfig/tcl.m4
new file mode 100644
index 0000000..8bc9c83
--- /dev/null
+++ b/tlt3.0/tclconfig/tcl.m4
@@ -0,0 +1,4150 @@
+# tcl.m4 --
+#
+# This file provides a set of autoconf macros to help TEA-enable
+# a Tcl extension.
+#
+# Copyright (c) 1999-2000 Ajuba Solutions.
+# Copyright (c) 2002-2005 ActiveState Corporation.
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+AC_PREREQ(2.57)
+
+dnl TEA extensions pass us the version of TEA they think they
+dnl are compatible with (must be set in TEA_INIT below)
+dnl TEA_VERSION="3.9"
+
+# Possible values for key variables defined:
+#
+# TEA_WINDOWINGSYSTEM - win32 aqua x11 (mirrors 'tk windowingsystem')
+# TEA_PLATFORM - windows unix
+#
+
+#------------------------------------------------------------------------
+# TEA_PATH_TCLCONFIG --
+#
+# Locate the tclConfig.sh file and perform a sanity check on
+# the Tcl compile flags
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tcl=...
+#
+# Defines the following vars:
+# TCL_BIN_DIR Full path to the directory containing
+# the tclConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_TCLCONFIG], [
+ dnl TEA specific: Make sure we are initialized
+ AC_REQUIRE([TEA_INIT])
+ #
+ # Ok, lets find the tcl configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tcl
+ #
+
+ if test x"${no_tcl}" = x ; then
+ # we reset no_tcl in case something fails here
+ no_tcl=true
+ AC_ARG_WITH(tcl,
+ AC_HELP_STRING([--with-tcl],
+ [directory containing tcl configuration (tclConfig.sh)]),
+ with_tclconfig="${withval}")
+ AC_MSG_CHECKING([for Tcl configuration])
+ AC_CACHE_VAL(ac_cv_c_tclconfig,[
+
+ # First check to see if --with-tcl was specified.
+ if test x"${with_tclconfig}" != x ; then
+ case "${with_tclconfig}" in
+ */tclConfig.sh )
+ if test -f "${with_tclconfig}"; then
+ AC_MSG_WARN([--with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself])
+ with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tclconfig}/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`"
+ else
+ AC_MSG_ERROR([${with_tclconfig} directory doesn't contain tclConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tcl installation
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ../tcl \
+ `ls -dr ../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../tcl \
+ `ls -dr ../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../tcl[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../../tcl \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tcl.framework/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # TEA specific: on Windows, check in common installation locations
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d C:/Tcl/lib 2>/dev/null` \
+ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ ; do
+ if test -f "$i/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tcl \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tcl[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tclConfig.sh" ; then
+ ac_cv_c_tclconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+ ])
+
+ if test x"${ac_cv_c_tclconfig}" = x ; then
+ TCL_BIN_DIR="# no Tcl configs found"
+ AC_MSG_ERROR([Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh])
+ else
+ no_tcl=
+ TCL_BIN_DIR="${ac_cv_c_tclconfig}"
+ AC_MSG_RESULT([found ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_TKCONFIG --
+#
+# Locate the tkConfig.sh file
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-tk=...
+#
+# Defines the following vars:
+# TK_BIN_DIR Full path to the directory containing
+# the tkConfig.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_TKCONFIG], [
+ #
+ # Ok, lets find the tk configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-tk
+ #
+
+ if test x"${no_tk}" = x ; then
+ # we reset no_tk in case something fails here
+ no_tk=true
+ AC_ARG_WITH(tk,
+ AC_HELP_STRING([--with-tk],
+ [directory containing tk configuration (tkConfig.sh)]),
+ with_tkconfig="${withval}")
+ AC_MSG_CHECKING([for Tk configuration])
+ AC_CACHE_VAL(ac_cv_c_tkconfig,[
+
+ # First check to see if --with-tkconfig was specified.
+ if test x"${with_tkconfig}" != x ; then
+ case "${with_tkconfig}" in
+ */tkConfig.sh )
+ if test -f "${with_tkconfig}"; then
+ AC_MSG_WARN([--with-tk argument should refer to directory containing tkConfig.sh, not to tkConfig.sh itself])
+ with_tkconfig="`echo "${with_tkconfig}" | sed 's!/tkConfig\.sh$!!'`"
+ fi ;;
+ esac
+ if test -f "${with_tkconfig}/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd "${with_tkconfig}"; pwd)`"
+ else
+ AC_MSG_ERROR([${with_tkconfig} directory doesn't contain tkConfig.sh])
+ fi
+ fi
+
+ # then check for a private Tk library
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ../tk \
+ `ls -dr ../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../tk \
+ `ls -dr ../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../tk[[8-9]].[[0-9]]* 2>/dev/null` \
+ ../../../tk \
+ `ls -dr ../../../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # on Darwin, check in Framework installation locations
+ if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ~/Library/Frameworks 2>/dev/null` \
+ `ls -d /Library/Frameworks 2>/dev/null` \
+ `ls -d /Network/Library/Frameworks 2>/dev/null` \
+ `ls -d /System/Library/Frameworks 2>/dev/null` \
+ ; do
+ if test -f "$i/Tk.framework/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/Tk.framework; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # TEA specific: on Windows, check in common installation locations
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a x"${ac_cv_c_tkconfig}" = x ; then
+ for i in `ls -d C:/Tcl/lib 2>/dev/null` \
+ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \
+ ; do
+ if test -f "$i/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i; pwd)`"
+ break
+ fi
+ done
+ fi
+
+ # check in a few other private locations
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ for i in \
+ ${srcdir}/../tk \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]].[[0-9]]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../tk[[8-9]].[[0-9]]* 2>/dev/null` ; do
+ if test "${TEA_PLATFORM}" = "windows" \
+ -a -f "$i/win/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/win; pwd)`"
+ break
+ fi
+ if test -f "$i/unix/tkConfig.sh" ; then
+ ac_cv_c_tkconfig="`(cd $i/unix; pwd)`"
+ break
+ fi
+ done
+ fi
+ ])
+
+ if test x"${ac_cv_c_tkconfig}" = x ; then
+ TK_BIN_DIR="# no Tk configs found"
+ AC_MSG_ERROR([Can't find Tk configuration definitions. Use --with-tk to specify a directory containing tkConfig.sh])
+ else
+ no_tk=
+ TK_BIN_DIR="${ac_cv_c_tkconfig}"
+ AC_MSG_RESULT([found ${TK_BIN_DIR}/tkConfig.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_TCLCONFIG --
+#
+# Load the tclConfig.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# TCL_BIN_DIR
+#
+# Results:
+#
+# Substitutes the following vars:
+# TCL_BIN_DIR
+# TCL_SRC_DIR
+# TCL_LIB_FILE
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_LOAD_TCLCONFIG], [
+ AC_MSG_CHECKING([for existence of ${TCL_BIN_DIR}/tclConfig.sh])
+
+ if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then
+ AC_MSG_RESULT([loading])
+ . "${TCL_BIN_DIR}/tclConfig.sh"
+ else
+ AC_MSG_RESULT([could not find ${TCL_BIN_DIR}/tclConfig.sh])
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\""
+ eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\""
+
+ # If the TCL_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TCL_LIB_SPEC will be set to the value
+ # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC
+ # instead of TCL_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}"
+ TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}"
+ TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tcl.framework installed in an arbitrary location.
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then
+ for i in "`cd "${TCL_BIN_DIR}"; pwd`" \
+ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then
+ TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then
+ TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}"
+ TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TCL_DBGX substitution
+ eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\""
+ eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\""
+ eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\""
+ eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\""
+
+ AC_SUBST(TCL_VERSION)
+ AC_SUBST(TCL_PATCH_LEVEL)
+ AC_SUBST(TCL_BIN_DIR)
+ AC_SUBST(TCL_SRC_DIR)
+
+ AC_SUBST(TCL_LIB_FILE)
+ AC_SUBST(TCL_LIB_FLAG)
+ AC_SUBST(TCL_LIB_SPEC)
+
+ AC_SUBST(TCL_STUB_LIB_FILE)
+ AC_SUBST(TCL_STUB_LIB_FLAG)
+ AC_SUBST(TCL_STUB_LIB_SPEC)
+
+ AC_MSG_CHECKING([platform])
+ hold_cc=$CC; CC="$TCL_CC"
+ AC_TRY_COMPILE(,[
+ #ifdef _WIN32
+ #error win32
+ #endif
+ ], TEA_PLATFORM="unix",
+ TEA_PLATFORM="windows"
+ )
+ CC=$hold_cc
+ AC_MSG_RESULT($TEA_PLATFORM)
+
+ # The BUILD_$pkg is to define the correct extern storage class
+ # handling when making this package
+ AC_DEFINE_UNQUOTED(BUILD_${PACKAGE_NAME}, [],
+ [Building extension source?])
+ # Do this here as we have fully defined TEA_PLATFORM now
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ EXEEXT=".exe"
+ CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp"
+ fi
+
+ # TEA specific:
+ AC_SUBST(CLEANFILES)
+ AC_SUBST(TCL_LIBS)
+ AC_SUBST(TCL_DEFS)
+ AC_SUBST(TCL_EXTRA_CFLAGS)
+ AC_SUBST(TCL_LD_FLAGS)
+ AC_SUBST(TCL_SHLIB_LD_LIBS)
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_TKCONFIG --
+#
+# Load the tkConfig.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# TK_BIN_DIR
+#
+# Results:
+#
+# Sets the following vars that should be in tkConfig.sh:
+# TK_BIN_DIR
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_LOAD_TKCONFIG], [
+ AC_MSG_CHECKING([for existence of ${TK_BIN_DIR}/tkConfig.sh])
+
+ if test -f "${TK_BIN_DIR}/tkConfig.sh" ; then
+ AC_MSG_RESULT([loading])
+ . "${TK_BIN_DIR}/tkConfig.sh"
+ else
+ AC_MSG_RESULT([could not find ${TK_BIN_DIR}/tkConfig.sh])
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FILE=\"${TK_LIB_FILE}\""
+ eval "TK_STUB_LIB_FILE=\"${TK_STUB_LIB_FILE}\""
+
+ # If the TK_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable TK_LIB_SPEC will be set to the value
+ # of TK_BUILD_LIB_SPEC. An extension should make use of TK_LIB_SPEC
+ # instead of TK_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ TK_LIB_SPEC="${TK_BUILD_LIB_SPEC}"
+ TK_STUB_LIB_SPEC="${TK_BUILD_STUB_LIB_SPEC}"
+ TK_STUB_LIB_PATH="${TK_BUILD_STUB_LIB_PATH}"
+ elif test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use the libraries
+ # from the framework at the given location so that linking works
+ # against Tk.framework installed in an arbitrary location.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -f "${TK_BIN_DIR}/${TK_LIB_FILE}"; then
+ for i in "`cd "${TK_BIN_DIR}"; pwd`" \
+ "`cd "${TK_BIN_DIR}"/../..; pwd`"; do
+ if test "`basename "$i"`" = "${TK_LIB_FILE}.framework"; then
+ TK_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TK_LIB_FILE}"
+ break
+ fi
+ done
+ fi
+ if test -f "${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"; then
+ TK_STUB_LIB_SPEC="-L` echo "${TK_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TK_STUB_LIB_FLAG}"
+ TK_STUB_LIB_PATH="${TK_BIN_DIR}/${TK_STUB_LIB_FILE}"
+ fi
+ ;;
+ esac
+ fi
+
+ # eval is required to do the TK_DBGX substitution
+ eval "TK_LIB_FLAG=\"${TK_LIB_FLAG}\""
+ eval "TK_LIB_SPEC=\"${TK_LIB_SPEC}\""
+ eval "TK_STUB_LIB_FLAG=\"${TK_STUB_LIB_FLAG}\""
+ eval "TK_STUB_LIB_SPEC=\"${TK_STUB_LIB_SPEC}\""
+
+ # TEA specific: Ensure windowingsystem is defined
+ if test "${TEA_PLATFORM}" = "unix" ; then
+ case ${TK_DEFS} in
+ *MAC_OSX_TK*)
+ AC_DEFINE(MAC_OSX_TK, 1, [Are we building against Mac OS X TkAqua?])
+ TEA_WINDOWINGSYSTEM="aqua"
+ ;;
+ *)
+ TEA_WINDOWINGSYSTEM="x11"
+ ;;
+ esac
+ elif test "${TEA_PLATFORM}" = "windows" ; then
+ TEA_WINDOWINGSYSTEM="win32"
+ fi
+
+ AC_SUBST(TK_VERSION)
+ AC_SUBST(TK_BIN_DIR)
+ AC_SUBST(TK_SRC_DIR)
+
+ AC_SUBST(TK_LIB_FILE)
+ AC_SUBST(TK_LIB_FLAG)
+ AC_SUBST(TK_LIB_SPEC)
+
+ AC_SUBST(TK_STUB_LIB_FILE)
+ AC_SUBST(TK_STUB_LIB_FLAG)
+ AC_SUBST(TK_STUB_LIB_SPEC)
+
+ # TEA specific:
+ AC_SUBST(TK_LIBS)
+ AC_SUBST(TK_XINCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_PROG_TCLSH
+# Determine the fully qualified path name of the tclsh executable
+# in the Tcl build directory or the tclsh installed in a bin
+# directory. This macro will correctly determine the name
+# of the tclsh executable even if tclsh has not yet been
+# built in the build directory. The tclsh found is always
+# associated with a tclConfig.sh file. This tclsh should be used
+# only for running extension test cases. It should never be
+# or generation of files (like pkgIndex.tcl) at build time.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following vars:
+# TCLSH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PROG_TCLSH], [
+ AC_MSG_CHECKING([for tclsh])
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ # tclConfig.sh is in Tcl build directory
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
+ else
+ TCLSH_PROG="${TCL_BIN_DIR}/tclsh"
+ fi
+ else
+ # tclConfig.sh is in install location
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}"
+ else
+ TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}"
+ fi
+ list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`"
+ for i in $list ; do
+ if test -f "$i/${TCLSH_PROG}" ; then
+ REAL_TCL_BIN_DIR="`cd "$i"; pwd`/"
+ break
+ fi
+ done
+ TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}"
+ fi
+ AC_MSG_RESULT([${TCLSH_PROG}])
+ AC_SUBST(TCLSH_PROG)
+])
+
+#------------------------------------------------------------------------
+# TEA_PROG_WISH
+# Determine the fully qualified path name of the wish executable
+# in the Tk build directory or the wish installed in a bin
+# directory. This macro will correctly determine the name
+# of the wish executable even if wish has not yet been
+# built in the build directory. The wish found is always
+# associated with a tkConfig.sh file. This wish should be used
+# only for running extension test cases. It should never be
+# or generation of files (like pkgIndex.tcl) at build time.
+#
+# Arguments:
+# none
+#
+# Results:
+# Substitutes the following vars:
+# WISH_PROG
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PROG_WISH], [
+ AC_MSG_CHECKING([for wish])
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ # tkConfig.sh is in Tk build directory
+ if test "${TEA_PLATFORM}" = "windows"; then
+ WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
+ else
+ WISH_PROG="${TK_BIN_DIR}/wish"
+ fi
+ else
+ # tkConfig.sh is in install location
+ if test "${TEA_PLATFORM}" = "windows"; then
+ WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}"
+ else
+ WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}"
+ fi
+ list="`ls -d ${TK_BIN_DIR}/../bin 2>/dev/null` \
+ `ls -d ${TK_BIN_DIR}/.. 2>/dev/null` \
+ `ls -d ${TK_PREFIX}/bin 2>/dev/null`"
+ for i in $list ; do
+ if test -f "$i/${WISH_PROG}" ; then
+ REAL_TK_BIN_DIR="`cd "$i"; pwd`/"
+ break
+ fi
+ done
+ WISH_PROG="${REAL_TK_BIN_DIR}${WISH_PROG}"
+ fi
+ AC_MSG_RESULT([${WISH_PROG}])
+ AC_SUBST(WISH_PROG)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_SHARED --
+#
+# Allows the building of shared libraries
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-shared=yes|no
+#
+# Defines the following vars:
+# STATIC_BUILD Used for building import/export libraries
+# on Windows.
+#
+# Sets the following vars:
+# SHARED_BUILD Value of 1 or 0
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_ENABLE_SHARED], [
+ AC_MSG_CHECKING([how to build libraries])
+ AC_ARG_ENABLE(shared,
+ AC_HELP_STRING([--enable-shared],
+ [build and link with shared libraries (default: on)]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+
+ if test "${enable_shared+set}" = set; then
+ enableval="$enable_shared"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" ; then
+ AC_MSG_RESULT([shared])
+ SHARED_BUILD=1
+ else
+ AC_MSG_RESULT([static])
+ SHARED_BUILD=0
+ AC_DEFINE(STATIC_BUILD, 1, [Is this a static build?])
+ fi
+ AC_SUBST(SHARED_BUILD)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_THREADS --
+#
+# Specify if thread support should be enabled. If "yes" is specified
+# as an arg (optional), threads are enabled by default, "no" means
+# threads are disabled. "yes" is the default.
+#
+# TCL_THREADS is checked so that if you are compiling an extension
+# against a threaded core, your extension must be compiled threaded
+# as well.
+#
+# Note that it is legal to have a thread enabled extension run in a
+# threaded or non-threaded Tcl core, but a non-threaded extension may
+# only run in a non-threaded Tcl core.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-threads
+#
+# Sets the following vars:
+# THREADS_LIBS Thread library(s)
+#
+# Defines the following vars:
+# TCL_THREADS
+# _REENTRANT
+# _THREAD_SAFE
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_ENABLE_THREADS], [
+ AC_ARG_ENABLE(threads,
+ AC_HELP_STRING([--enable-threads],
+ [build with threads]),
+ [tcl_ok=$enableval], [tcl_ok=yes])
+
+ if test "${enable_threads+set}" = set; then
+ enableval="$enable_threads"
+ tcl_ok=$enableval
+ else
+ tcl_ok=yes
+ fi
+
+ if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then
+ TCL_THREADS=1
+
+ if test "${TEA_PLATFORM}" != "windows" ; then
+ # We are always OK on Windows, so check what this platform wants:
+
+ # USE_THREAD_ALLOC tells us to try the special thread-based
+ # allocator that significantly reduces lock contention
+ AC_DEFINE(USE_THREAD_ALLOC, 1,
+ [Do we want to use the threaded memory allocator?])
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ if test "`uname -s`" = "SunOS" ; then
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+ fi
+ AC_DEFINE(_THREAD_SAFE, 1, [Do we want the thread-safe OS API?])
+ AC_CHECK_LIB(pthread,pthread_mutex_init,tcl_ok=yes,tcl_ok=no)
+ if test "$tcl_ok" = "no"; then
+ # Check a little harder for __pthread_mutex_init in the same
+ # library, as some systems hide it there until pthread.h is
+ # defined. We could alternatively do an AC_TRY_COMPILE with
+ # pthread.h, but that will work with libpthread really doesn't
+ # exist, like AIX 4.2. [Bug: 4359]
+ AC_CHECK_LIB(pthread, __pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ fi
+
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthread"
+ else
+ AC_CHECK_LIB(pthreads, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -lpthreads"
+ else
+ AC_CHECK_LIB(c, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "no"; then
+ AC_CHECK_LIB(c_r, pthread_mutex_init,
+ tcl_ok=yes, tcl_ok=no)
+ if test "$tcl_ok" = "yes"; then
+ # The space is needed
+ THREADS_LIBS=" -pthread"
+ else
+ TCL_THREADS=0
+ AC_MSG_WARN([Do not know how to find pthread lib on your system - thread support disabled])
+ fi
+ fi
+ fi
+ fi
+ fi
+ else
+ TCL_THREADS=0
+ fi
+ # Do checking message here to not mess up interleaved configure output
+ AC_MSG_CHECKING([for building with threads])
+ if test "${TCL_THREADS}" = 1; then
+ AC_DEFINE(TCL_THREADS, 1, [Are we building with threads enabled?])
+ AC_MSG_RESULT([yes (default)])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ # TCL_THREADS sanity checking. See if our request for building with
+ # threads is the same as the way Tcl was built. If not, warn the user.
+ case ${TCL_DEFS} in
+ *THREADS=1*)
+ if test "${TCL_THREADS}" = "0"; then
+ AC_MSG_WARN([
+ Building ${PACKAGE_NAME} without threads enabled, but building against Tcl
+ that IS thread-enabled. It is recommended to use --enable-threads.])
+ fi
+ ;;
+ *)
+ if test "${TCL_THREADS}" = "1"; then
+ AC_MSG_WARN([
+ --enable-threads requested, but building against a Tcl that is NOT
+ thread-enabled. This is an OK configuration that will also run in
+ a thread-enabled core.])
+ fi
+ ;;
+ esac
+ AC_SUBST(TCL_THREADS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_SYMBOLS --
+#
+# Specify if debugging symbols should be used.
+# Memory (TCL_MEM_DEBUG) debugging can also be enabled.
+#
+# Arguments:
+# none
+#
+# TEA varies from core Tcl in that C|LDFLAGS_DEFAULT receives
+# the value of C|LDFLAGS_OPTIMIZE|DEBUG already substituted.
+# Requires the following vars to be set in the Makefile:
+# CFLAGS_DEFAULT
+# LDFLAGS_DEFAULT
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-symbols
+#
+# Defines the following vars:
+# CFLAGS_DEFAULT Sets to $(CFLAGS_DEBUG) if true
+# Sets to "$(CFLAGS_OPTIMIZE) -DNDEBUG" if false
+# LDFLAGS_DEFAULT Sets to $(LDFLAGS_DEBUG) if true
+# Sets to $(LDFLAGS_OPTIMIZE) if false
+# DBGX Formerly used as debug library extension;
+# always blank now.
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_ENABLE_SYMBOLS], [
+ dnl TEA specific: Make sure we are initialized
+ AC_REQUIRE([TEA_CONFIG_CFLAGS])
+ AC_MSG_CHECKING([for build with symbols])
+ AC_ARG_ENABLE(symbols,
+ AC_HELP_STRING([--enable-symbols],
+ [build with debugging symbols (default: off)]),
+ [tcl_ok=$enableval], [tcl_ok=no])
+ DBGX=""
+ if test "$tcl_ok" = "no"; then
+ CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG"
+ LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}"
+ AC_MSG_RESULT([no])
+ else
+ CFLAGS_DEFAULT="${CFLAGS_DEBUG}"
+ LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}"
+ if test "$tcl_ok" = "yes"; then
+ AC_MSG_RESULT([yes (standard debugging)])
+ fi
+ fi
+ # TEA specific:
+ if test "${TEA_PLATFORM}" != "windows" ; then
+ LDFLAGS_DEFAULT="${LDFLAGS}"
+ fi
+ AC_SUBST(CFLAGS_DEFAULT)
+ AC_SUBST(LDFLAGS_DEFAULT)
+ AC_SUBST(TCL_DBGX)
+
+ if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then
+ AC_DEFINE(TCL_MEM_DEBUG, 1, [Is memory debugging enabled?])
+ fi
+
+ if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then
+ if test "$tcl_ok" = "all"; then
+ AC_MSG_RESULT([enabled symbols mem debugging])
+ else
+ AC_MSG_RESULT([enabled $tcl_ok debugging])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_ENABLE_LANGINFO --
+#
+# Allows use of modern nl_langinfo check for better l10n.
+# This is only relevant for Unix.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --enable-langinfo=yes|no (default is yes)
+#
+# Defines the following vars:
+# HAVE_LANGINFO Triggers use of nl_langinfo if defined.
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_ENABLE_LANGINFO], [
+ AC_ARG_ENABLE(langinfo,
+ AC_HELP_STRING([--enable-langinfo],
+ [use nl_langinfo if possible to determine encoding at startup, otherwise use old heuristic (default: on)]),
+ [langinfo_ok=$enableval], [langinfo_ok=yes])
+
+ HAVE_LANGINFO=0
+ if test "$langinfo_ok" = "yes"; then
+ AC_CHECK_HEADER(langinfo.h,[langinfo_ok=yes],[langinfo_ok=no])
+ fi
+ AC_MSG_CHECKING([whether to use nl_langinfo])
+ if test "$langinfo_ok" = "yes"; then
+ AC_CACHE_VAL(tcl_cv_langinfo_h, [
+ AC_TRY_COMPILE([#include <langinfo.h>], [nl_langinfo(CODESET);],
+ [tcl_cv_langinfo_h=yes],[tcl_cv_langinfo_h=no])])
+ AC_MSG_RESULT([$tcl_cv_langinfo_h])
+ if test $tcl_cv_langinfo_h = yes; then
+ AC_DEFINE(HAVE_LANGINFO, 1, [Do we have nl_langinfo()?])
+ fi
+ else
+ AC_MSG_RESULT([$langinfo_ok])
+ fi
+])
+
+#--------------------------------------------------------------------
+# TEA_CONFIG_SYSTEM
+#
+# Determine what the system is (some things cannot be easily checked
+# on a feature-driven basis, alas). This can usually be done via the
+# "uname" command.
+#
+# Arguments:
+# none
+#
+# Results:
+# Defines the following var:
+#
+# system - System/platform/version identification code.
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_CONFIG_SYSTEM], [
+ AC_CACHE_CHECK([system version], tcl_cv_sys_version, [
+ # TEA specific:
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ tcl_cv_sys_version=windows
+ else
+ tcl_cv_sys_version=`uname -s`-`uname -r`
+ if test "$?" -ne 0 ; then
+ AC_MSG_WARN([can't find uname command])
+ tcl_cv_sys_version=unknown
+ else
+ if test "`uname -s`" = "AIX" ; then
+ tcl_cv_sys_version=AIX-`uname -v`.`uname -r`
+ fi
+ fi
+ fi
+ ])
+ system=$tcl_cv_sys_version
+])
+
+#--------------------------------------------------------------------
+# TEA_CONFIG_CFLAGS
+#
+# Try to determine the proper flags to pass to the compiler
+# for building shared libraries and other such nonsense.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines and substitutes the following vars:
+#
+# DL_OBJS, DL_LIBS - removed for TEA, only needed by core.
+# LDFLAGS - Flags to pass to the compiler when linking object
+# files into an executable application binary such
+# as tclsh.
+# LD_SEARCH_FLAGS-Flags to pass to ld, such as "-R /usr/local/tcl/lib",
+# that tell the run-time dynamic linker where to look
+# for shared libraries such as libtcl.so. Depends on
+# the variable LIB_RUNTIME_DIR in the Makefile. Could
+# be the same as CC_SEARCH_FLAGS if ${CC} is used to link.
+# CC_SEARCH_FLAGS-Flags to pass to ${CC}, such as "-Wl,-rpath,/usr/local/tcl/lib",
+# that tell the run-time dynamic linker where to look
+# for shared libraries such as libtcl.so. Depends on
+# the variable LIB_RUNTIME_DIR in the Makefile.
+# SHLIB_CFLAGS - Flags to pass to cc when compiling the components
+# of a shared library (may request position-independent
+# code, among other things).
+# SHLIB_LD - Base command to use for combining object files
+# into a shared library.
+# SHLIB_LD_LIBS - Dependent libraries for the linker to scan when
+# creating shared libraries. This symbol typically
+# goes at the end of the "ld" commands that build
+# shared libraries. The value of the symbol defaults to
+# "${LIBS}" if all of the dependent libraries should
+# be specified when creating a shared library. If
+# dependent libraries should not be specified (as on
+# SunOS 4.x, where they cause the link to fail, or in
+# general if Tcl and Tk aren't themselves shared
+# libraries), then this symbol has an empty string
+# as its value.
+# SHLIB_SUFFIX - Suffix to use for the names of dynamically loadable
+# extensions. An empty string means we don't know how
+# to use shared libraries on this platform.
+# LIB_SUFFIX - Specifies everything that comes after the "libfoo"
+# in a static or shared library name, using the $PACKAGE_VERSION variable
+# to put the version in the right place. This is used
+# by platforms that need non-standard library names.
+# Examples: ${PACKAGE_VERSION}.so.1.1 on NetBSD, since it needs
+# to have a version after the .so, and ${PACKAGE_VERSION}.a
+# on AIX, since a shared library needs to have
+# a .a extension whereas shared objects for loadable
+# extensions have a .so extension. Defaults to
+# ${PACKAGE_VERSION}${SHLIB_SUFFIX}.
+# CFLAGS_DEBUG -
+# Flags used when running the compiler in debug mode
+# CFLAGS_OPTIMIZE -
+# Flags used when running the compiler in optimize mode
+# CFLAGS - Additional CFLAGS added as necessary (usually 64-bit)
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_CONFIG_CFLAGS], [
+ dnl TEA specific: Make sure we are initialized
+ AC_REQUIRE([TEA_INIT])
+
+ # Step 0.a: Enable 64 bit support?
+
+ AC_MSG_CHECKING([if 64bit support is requested])
+ AC_ARG_ENABLE(64bit,
+ AC_HELP_STRING([--enable-64bit],
+ [enable 64bit support (default: off)]),
+ [do64bit=$enableval], [do64bit=no])
+ AC_MSG_RESULT([$do64bit])
+
+ # Step 0.b: Enable Solaris 64 bit VIS support?
+
+ AC_MSG_CHECKING([if 64bit Sparc VIS support is requested])
+ AC_ARG_ENABLE(64bit-vis,
+ AC_HELP_STRING([--enable-64bit-vis],
+ [enable 64bit Sparc VIS support (default: off)]),
+ [do64bitVIS=$enableval], [do64bitVIS=no])
+ AC_MSG_RESULT([$do64bitVIS])
+ # Force 64bit on with VIS
+ AS_IF([test "$do64bitVIS" = "yes"], [do64bit=yes])
+
+ # Step 0.c: Check if visibility support is available. Do this here so
+ # that platform specific alternatives can be used below if this fails.
+
+ AC_CACHE_CHECK([if compiler supports visibility "hidden"],
+ tcl_cv_cc_visibility_hidden, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror"
+ AC_TRY_LINK([
+ extern __attribute__((__visibility__("hidden"))) void f(void);
+ void f(void) {}], [f();], tcl_cv_cc_visibility_hidden=yes,
+ tcl_cv_cc_visibility_hidden=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_visibility_hidden = yes], [
+ AC_DEFINE(MODULE_SCOPE,
+ [extern __attribute__((__visibility__("hidden")))],
+ [Compiler support for module scope symbols])
+ AC_DEFINE(HAVE_HIDDEN, [1], [Compiler support for module scope symbols])
+ ])
+
+ # Step 0.d: Disable -rpath support?
+
+ AC_MSG_CHECKING([if rpath support is requested])
+ AC_ARG_ENABLE(rpath,
+ AC_HELP_STRING([--disable-rpath],
+ [disable rpath support (default: on)]),
+ [doRpath=$enableval], [doRpath=yes])
+ AC_MSG_RESULT([$doRpath])
+
+ # TEA specific: Cross-compiling options for Windows/CE builds?
+
+ AS_IF([test "${TEA_PLATFORM}" = windows], [
+ AC_MSG_CHECKING([if Windows/CE build is requested])
+ AC_ARG_ENABLE(wince,
+ AC_HELP_STRING([--enable-wince],
+ [enable Win/CE support (where applicable)]),
+ [doWince=$enableval], [doWince=no])
+ AC_MSG_RESULT([$doWince])
+ ])
+
+ # Set the variable "system" to hold the name and version number
+ # for the system.
+
+ TEA_CONFIG_SYSTEM
+
+ # Require ranlib early so we can override it in special cases below.
+
+ AC_REQUIRE([AC_PROG_RANLIB])
+
+ # Set configuration options based on system name and version.
+ # This is similar to Tcl's unix/tcl.m4 except that we've added a
+ # "windows" case and removed some core-only vars.
+
+ do64bit_ok=no
+ # default to '{$LIBS}' and set to "" on per-platform necessary basis
+ SHLIB_LD_LIBS='${LIBS}'
+ # When ld needs options to work in 64-bit mode, put them in
+ # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load]
+ # is disabled by the user. [Bug 1016796]
+ LDFLAGS_ARCH=""
+ UNSHARED_LIB_SUFFIX=""
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`'
+ ECHO_VERSION='`echo ${PACKAGE_VERSION}`'
+ TCL_LIB_VERSIONS_OK=ok
+ CFLAGS_DEBUG=-g
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS_OPTIMIZE=-O2
+ CFLAGS_WARNING="-Wall"
+ ], [
+ CFLAGS_OPTIMIZE=-O
+ CFLAGS_WARNING=""
+ ])
+ AC_CHECK_TOOL(AR, ar)
+ STLIB_LD='${AR} cr'
+ LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH"
+ AS_IF([test "x$SHLIB_VERSION" = x],[SHLIB_VERSION="1.0"])
+ case $system in
+ # TEA specific:
+ windows)
+ # This is a 2-stage check to make sure we have the 64-bit SDK
+ # We have to know where the SDK is installed.
+ # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs
+ # MACHINE is IX86 for LINK, but this is used by the manifest,
+ # which requires x86|amd64|ia64.
+ MACHINE="X86"
+ if test "$do64bit" != "no" ; then
+ if test "x${MSSDK}x" = "xx" ; then
+ MSSDK="C:/Progra~1/Microsoft Platform SDK"
+ fi
+ MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'`
+ PATH64=""
+ case "$do64bit" in
+ amd64|x64|yes)
+ MACHINE="AMD64" ; # default to AMD64 64-bit build
+ PATH64="${MSSDK}/Bin/Win64/x86/AMD64"
+ ;;
+ ia64)
+ MACHINE="IA64"
+ PATH64="${MSSDK}/Bin/Win64"
+ ;;
+ esac
+ if test "$GCC" != "yes" -a ! -d "${PATH64}" ; then
+ AC_MSG_WARN([Could not find 64-bit $MACHINE SDK to enable 64bit mode])
+ AC_MSG_WARN([Ensure latest Platform SDK is installed])
+ do64bit="no"
+ else
+ AC_MSG_RESULT([ Using 64-bit $MACHINE mode])
+ do64bit_ok="yes"
+ fi
+ fi
+
+ if test "$doWince" != "no" ; then
+ if test "$do64bit" != "no" ; then
+ AC_MSG_ERROR([Windows/CE and 64-bit builds incompatible])
+ fi
+ if test "$GCC" = "yes" ; then
+ AC_MSG_ERROR([Windows/CE and GCC builds incompatible])
+ fi
+ TEA_PATH_CELIB
+ # Set defaults for common evc4/PPC2003 setup
+ # Currently Tcl requires 300+, possibly 420+ for sockets
+ CEVERSION=420; # could be 211 300 301 400 420 ...
+ TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ...
+ ARCH=ARM; # could be ARM MIPS X86EM ...
+ PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002"
+ if test "$doWince" != "yes"; then
+ # If !yes then the user specified something
+ # Reset ARCH to allow user to skip specifying it
+ ARCH=
+ eval `echo $doWince | awk -F, '{ \
+ if (length([$]1)) { printf "CEVERSION=\"%s\"\n", [$]1; \
+ if ([$]1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \
+ if (length([$]2)) { printf "TARGETCPU=\"%s\"\n", toupper([$]2) }; \
+ if (length([$]3)) { printf "ARCH=\"%s\"\n", toupper([$]3) }; \
+ if (length([$]4)) { printf "PLATFORM=\"%s\"\n", [$]4 }; \
+ }'`
+ if test "x${ARCH}" = "x" ; then
+ ARCH=$TARGETCPU;
+ fi
+ fi
+ OSVERSION=WCE$CEVERSION;
+ if test "x${WCEROOT}" = "x" ; then
+ WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0"
+ if test ! -d "${WCEROOT}" ; then
+ WCEROOT="C:/Program Files/Microsoft eMbedded Tools"
+ fi
+ fi
+ if test "x${SDKROOT}" = "x" ; then
+ SDKROOT="C:/Program Files/Windows CE Tools"
+ if test ! -d "${SDKROOT}" ; then
+ SDKROOT="C:/Windows CE Tools"
+ fi
+ fi
+ WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'`
+ SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'`
+ if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" \
+ -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then
+ AC_MSG_ERROR([could not find PocketPC SDK or target compiler to enable WinCE mode [$CEVERSION,$TARGETCPU,$ARCH,$PLATFORM]])
+ doWince="no"
+ else
+ # We could PATH_NOSPACE these, but that's not important,
+ # as long as we quote them when used.
+ CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include"
+ if test -d "${CEINCLUDE}/${TARGETCPU}" ; then
+ CEINCLUDE="${CEINCLUDE}/${TARGETCPU}"
+ fi
+ CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"
+ fi
+ fi
+
+ if test "$GCC" != "yes" ; then
+ if test "${SHARED_BUILD}" = "0" ; then
+ runtime=-MT
+ else
+ runtime=-MD
+ fi
+
+ if test "$do64bit" != "no" ; then
+ # All this magic is necessary for the Win64 SDK RC1 - hobbs
+ CC="\"${PATH64}/cl.exe\""
+ CFLAGS="${CFLAGS} -I\"${MSSDK}/Include\" -I\"${MSSDK}/Include/crt\" -I\"${MSSDK}/Include/crt/sys\""
+ RC="\"${MSSDK}/bin/rc.exe\""
+ lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\""
+ LINKBIN="\"${PATH64}/link.exe\""
+ CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d"
+ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+ # Avoid 'unresolved external symbol __security_cookie'
+ # errors, c.f. http://support.microsoft.com/?id=894573
+ TEA_ADD_LIBS([bufferoverflowU.lib])
+ elif test "$doWince" != "no" ; then
+ CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin"
+ if test "${TARGETCPU}" = "X86"; then
+ CC="\"${CEBINROOT}/cl.exe\""
+ else
+ CC="\"${CEBINROOT}/cl${ARCH}.exe\""
+ fi
+ CFLAGS="$CFLAGS -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\""
+ RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\""
+ arch=`echo ${ARCH} | awk '{print tolower([$]0)}'`
+ defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _WINDOWS"
+ if test "${SHARED_BUILD}" = "1" ; then
+ # Static CE builds require static celib as well
+ defs="${defs} _DLL"
+ fi
+ for i in $defs ; do
+ AC_DEFINE_UNQUOTED($i, 1, [WinCE def ]$i)
+ done
+ AC_DEFINE_UNQUOTED(_WIN32_WCE, $CEVERSION, [_WIN32_WCE version])
+ AC_DEFINE_UNQUOTED(UNDER_CE, $CEVERSION, [UNDER_CE version])
+ CFLAGS_DEBUG="-nologo -Zi -Od"
+ CFLAGS_OPTIMIZE="-nologo -Ox"
+ lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'`
+ lflags="-MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo"
+ LINKBIN="\"${CEBINROOT}/link.exe\""
+ AC_SUBST(CELIB_DIR)
+ else
+ RC="rc"
+ lflags="-nologo"
+ LINKBIN="link"
+ CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d"
+ CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}"
+ fi
+ fi
+
+ if test "$GCC" = "yes"; then
+ # mingw gcc mode
+ AC_CHECK_TOOL(RC, windres)
+ CFLAGS_DEBUG="-g"
+ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+ SHLIB_LD='${CC} -shared'
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}"
+ LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}"
+
+ AC_CACHE_CHECK(for cross-compile version of gcc,
+ ac_cv_cross,
+ AC_TRY_COMPILE([
+ #ifdef __WIN32__
+ #error cross-compiler
+ #endif
+ ], [],
+ ac_cv_cross=yes,
+ ac_cv_cross=no)
+ )
+ if test "$ac_cv_cross" = "yes"; then
+ case "$do64bit" in
+ amd64|x64|yes)
+ CC="x86_64-w64-mingw32-gcc"
+ LD="x86_64-w64-mingw32-ld"
+ AR="x86_64-w64-mingw32-ar"
+ RANLIB="x86_64-w64-mingw32-ranlib"
+ RC="x86_64-w64-mingw32-windres"
+ ;;
+ *)
+ CC="i686-w64-mingw32-gcc"
+ LD="i686-w64-mingw32-ld"
+ AR="i686-w64-mingw32-ar"
+ RANLIB="i686-w64-mingw32-ranlib"
+ RC="i686-w64-mingw32-windres"
+ ;;
+ esac
+ fi
+
+ else
+ SHLIB_LD="${LINKBIN} -dll ${lflags}"
+ # link -lib only works when -lib is the first arg
+ STLIB_LD="${LINKBIN} -lib ${lflags}"
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib'
+ PATHTYPE=-w
+ # For information on what debugtype is most useful, see:
+ # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp
+ # and also
+ # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx
+ # This essentially turns it all on.
+ LDFLAGS_DEBUG="-debug -debugtype:cv"
+ LDFLAGS_OPTIMIZE="-release"
+ if test "$doWince" != "no" ; then
+ LDFLAGS_CONSOLE="-link ${lflags}"
+ LDFLAGS_WINDOW=${LDFLAGS_CONSOLE}
+ else
+ LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}"
+ LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}"
+ fi
+ fi
+
+ SHLIB_SUFFIX=".dll"
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll'
+
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ AIX-*)
+ AS_IF([test "${TCL_THREADS}" = "1" -a "$GCC" != "yes"], [
+ # AIX requires the _r compiler when gcc isn't being used
+ case "${CC}" in
+ *_r|*_r\ *)
+ # ok ...
+ ;;
+ *)
+ # Make sure only first arg gets _r
+ CC=`echo "$CC" | sed -e 's/^\([[^ ]]*\)/\1_r/'`
+ ;;
+ esac
+ AC_MSG_RESULT([Using $CC for compiling with threads])
+ ])
+ LIBS="$LIBS -lc"
+ SHLIB_CFLAGS=""
+ SHLIB_SUFFIX=".so"
+
+ LD_LIBRARY_PATH_VAR="LIBPATH"
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -q64"
+ LDFLAGS_ARCH="-q64"
+ RANLIB="${RANLIB} -X64"
+ AR="${AR} -X64"
+ SHLIB_LD_FLAGS="-b64"
+ ])
+ ])
+
+ AS_IF([test "`uname -m`" = ia64], [
+ # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ AS_IF([test "$GCC" = yes], [
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ ], [
+ CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}'
+ ])
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ], [
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared -Wl,-bexpall'
+ ], [
+ SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry"
+ LDFLAGS="$LDFLAGS -brtl"
+ ])
+ SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}"
+ CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ BeOS*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -nostart'
+ SHLIB_SUFFIX=".so"
+
+ #-----------------------------------------------------------
+ # Check for inet_ntoa in -lbind, for BeOS (which also needs
+ # -lsocket, even if the network functions are in -lnet which
+ # is always linked to, for compatibility.
+ #-----------------------------------------------------------
+ AC_CHECK_LIB(bind, inet_ntoa, [LIBS="$LIBS -lbind -lsocket"])
+ ;;
+ BSD/OS-4.*)
+ SHLIB_CFLAGS="-export-dynamic -fPIC"
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".so"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ CYGWIN_*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD='${CC} -shared'
+ SHLIB_SUFFIX=".dll"
+ EXEEXT=".exe"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ Haiku*)
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}'
+ AC_CHECK_LIB(network, inet_ntoa, [LIBS="$LIBS -lnetwork"])
+ ;;
+ HP-UX-*.11.*)
+ # Use updated header definitions where possible
+ AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Do we want to use the XOPEN network library?])
+ # TEA specific: Needed by Tcl, but not most extensions
+ #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?])
+ #LIBS="$LIBS -lxnet" # Use the XOPEN network library
+
+ AS_IF([test "`uname -m`" = ia64], [
+ SHLIB_SUFFIX=".so"
+ # Use newer C++ library for C++ extensions
+ #if test "$GCC" != "yes" ; then
+ # CPPFLAGS="-AA"
+ #fi
+ ], [
+ SHLIB_SUFFIX=".sl"
+ ])
+ AC_CHECK_LIB(dld, shl_load, tcl_ok=yes, tcl_ok=no)
+ AS_IF([test "$tcl_ok" = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-E"
+ CC_SEARCH_FLAGS='-Wl,+s,+b,${LIB_RUNTIME_DIR}:.'
+ LD_SEARCH_FLAGS='+s +b ${LIB_RUNTIME_DIR}:.'
+ LD_LIBRARY_PATH_VAR="SHLIB_PATH"
+ ])
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ CFLAGS="$CFLAGS -z"
+ # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc
+ #CFLAGS="$CFLAGS +DAportable"
+ SHLIB_CFLAGS="+z"
+ SHLIB_LD="ld -b"
+ ])
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = "yes"], [
+ AS_IF([test "$GCC" = yes], [
+ case `${CC} -dumpmachine` in
+ hppa64*)
+ # 64-bit gcc in use. Fix flags for GNU ld.
+ do64bit_ok=yes
+ SHLIB_LD='${CC} -shared'
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ;;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system])
+ ;;
+ esac
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS +DD64"
+ LDFLAGS_ARCH="+DD64"
+ ])
+ ]) ;;
+ IRIX-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [
+ CFLAGS="$CFLAGS -mabi=n32"
+ LDFLAGS="$LDFLAGS -mabi=n32"
+ ], [
+ case $system in
+ IRIX-6.3)
+ # Use to build 6.2 compatible binaries on 6.3.
+ CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS"
+ ;;
+ *)
+ CFLAGS="$CFLAGS -n32"
+ ;;
+ esac
+ LDFLAGS="$LDFLAGS -n32"
+ ])
+ ;;
+ IRIX64-6.*)
+ SHLIB_CFLAGS=""
+ SHLIB_LD="ld -n32 -shared -rdata_shared"
+ SHLIB_SUFFIX=".so"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+
+ # Check to enable 64-bit flags for compiler/linker
+
+ AS_IF([test "$do64bit" = yes], [
+ AS_IF([test "$GCC" = yes], [
+ AC_MSG_WARN([64bit mode not supported by gcc])
+ ], [
+ do64bit_ok=yes
+ SHLIB_LD="ld -64 -shared -rdata_shared"
+ CFLAGS="$CFLAGS -64"
+ LDFLAGS_ARCH="-64"
+ ])
+ ])
+ ;;
+ Linux*|GNU*|NetBSD-Debian)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+
+ # TEA specific:
+ CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer"
+
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS_DEFAULT}'
+ LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "`uname -m`" = "alpha"], [CFLAGS="$CFLAGS -mieee"])
+ AS_IF([test $do64bit = yes], [
+ AC_CACHE_CHECK([if compiler accepts -m64 flag], tcl_cv_cc_m64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -m64"
+ AC_TRY_LINK(,, tcl_cv_cc_m64=yes, tcl_cv_cc_m64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_m64 = yes], [
+ CFLAGS="$CFLAGS -m64"
+ do64bit_ok=yes
+ ])
+ ])
+
+ # The combo of gcc + glibc has a bug related to inlining of
+ # functions like strtod(). The -fno-builtin flag should address
+ # this problem but it does not work. The -fno-inline flag is kind
+ # of overkill but it works. Disable inlining only when one of the
+ # files in compat/*.c is being linked in.
+
+ AS_IF([test x"${USE_COMPAT}" != x],[CFLAGS="$CFLAGS -fno-inline"])
+ ;;
+ Lynx*)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_SUFFIX=".so"
+ CFLAGS_OPTIMIZE=-02
+ SHLIB_LD='${CC} -shared'
+ LD_FLAGS="-Wl,--export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ ;;
+ OpenBSD-*)
+ arch=`arch -s`
+ case "$arch" in
+ vax)
+ SHLIB_SUFFIX=""
+ SHARED_LIB_SUFFIX=""
+ LDFLAGS=""
+ ;;
+ *)
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}'
+ LDFLAGS="-Wl,-export-dynamic"
+ ;;
+ esac
+ case "$arch" in
+ vax)
+ CFLAGS_OPTIMIZE="-O1"
+ ;;
+ *)
+ CFLAGS_OPTIMIZE="-O2"
+ ;;
+ esac
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # On OpenBSD: Compile with -pthread
+ # Don't link with -lpthread
+ LIBS=`echo $LIBS | sed s/-lpthread//`
+ CFLAGS="$CFLAGS -pthread"
+ ])
+ # OpenBSD doesn't do version numbers with dots.
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ NetBSD-*)
+ # NetBSD has ELF and can use 'cc -shared' to build shared libs
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}'
+ SHLIB_SUFFIX=".so"
+ LDFLAGS="$LDFLAGS -export-dynamic"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the CFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ;;
+ FreeBSD-*)
+ # This configuration from FreeBSD Ports.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="${CC} -shared"
+ TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$[@]"
+ SHLIB_SUFFIX=".so"
+ LDFLAGS=""
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'])
+ AS_IF([test "${TCL_THREADS}" = "1"], [
+ # The -pthread needs to go in the LDFLAGS, not LIBS
+ LIBS=`echo $LIBS | sed s/-pthread//`
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ LDFLAGS="$LDFLAGS $PTHREAD_LIBS"])
+ # Version numbers are dot-stripped by system policy.
+ TCL_TRIM_DOTS=`echo ${PACKAGE_VERSION} | tr -d .`
+ UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a'
+ SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1'
+ TCL_LIB_VERSIONS_OK=nodots
+ ;;
+ Darwin-*)
+ CFLAGS_OPTIMIZE="-Os"
+ SHLIB_CFLAGS="-fno-common"
+ # To avoid discrepancies between what headers configure sees during
+ # preprocessing tests and compiling tests, move any -isysroot and
+ # -mmacosx-version-min flags from CFLAGS to CPPFLAGS:
+ CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if ([$]i~/^(isysroot|mmacosx-version-min)/) print "-"[$]i}'`"
+ CFLAGS="`echo " ${CFLAGS}" | \
+ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \
+ if (!([$]i~/^(isysroot|mmacosx-version-min)/)) print "-"[$]i}'`"
+ AS_IF([test $do64bit = yes], [
+ case `arch` in
+ ppc)
+ AC_CACHE_CHECK([if compiler accepts -arch ppc64 flag],
+ tcl_cv_cc_arch_ppc64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_ppc64=yes,
+ tcl_cv_cc_arch_ppc64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_ppc64 = yes], [
+ CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5"
+ do64bit_ok=yes
+ ]);;
+ i386)
+ AC_CACHE_CHECK([if compiler accepts -arch x86_64 flag],
+ tcl_cv_cc_arch_x86_64, [
+ hold_cflags=$CFLAGS
+ CFLAGS="$CFLAGS -arch x86_64"
+ AC_TRY_LINK(,, tcl_cv_cc_arch_x86_64=yes,
+ tcl_cv_cc_arch_x86_64=no)
+ CFLAGS=$hold_cflags])
+ AS_IF([test $tcl_cv_cc_arch_x86_64 = yes], [
+ CFLAGS="$CFLAGS -arch x86_64"
+ do64bit_ok=yes
+ ]);;
+ *)
+ AC_MSG_WARN([Don't know how enable 64-bit on architecture `arch`]);;
+ esac
+ ], [
+ # Check for combined 32-bit and 64-bit fat build
+ AS_IF([echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \
+ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) '], [
+ fat_32_64=yes])
+ ])
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}'
+ AC_CACHE_CHECK([if ld accepts -single_module flag], tcl_cv_ld_single_module, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_single_module=yes, tcl_cv_ld_single_module=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_single_module = yes], [
+ SHLIB_LD="${SHLIB_LD} -Wl,-single_module"
+ ])
+ # TEA specific: link shlib with current and compatibility version flags
+ vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([[0-9]]\{1,5\}\)\(\(\.[[0-9]]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d`
+ SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}"
+ SHLIB_SUFFIX=".dylib"
+ # Don't use -prebind when building for Mac OS X 10.4 or later only:
+ AS_IF([test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int([$]2)}'`" -lt 4 -a \
+ "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int([$]2)}'`" -lt 4], [
+ LDFLAGS="$LDFLAGS -prebind"])
+ LDFLAGS="$LDFLAGS -headerpad_max_install_names"
+ AC_CACHE_CHECK([if ld accepts -search_paths_first flag],
+ tcl_cv_ld_search_paths_first, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_search_paths_first=yes,
+ tcl_cv_ld_search_paths_first=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_search_paths_first = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-search_paths_first"
+ ])
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [__private_extern__],
+ [Compiler support for module scope symbols])
+ tcl_cv_cc_visibility_hidden=yes
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH"
+ # TEA specific: for combined 32 & 64 bit fat builds of Tk
+ # extensions, verify that 64-bit build is possible.
+ AS_IF([test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}"], [
+ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = x11], [
+ AC_CACHE_CHECK([for 64-bit X11], tcl_cv_lib_x11_64, [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include"
+ LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11"
+ AC_TRY_LINK([#include <X11/Xlib.h>], [XrmInitialize();],
+ tcl_cv_lib_x11_64=yes, tcl_cv_lib_x11_64=no)
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ ])
+ AS_IF([test "${TEA_WINDOWINGSYSTEM}" = aqua], [
+ AC_CACHE_CHECK([for 64-bit Tk], tcl_cv_lib_tk_64, [
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"'
+ done
+ CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}"
+ LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}"
+ AC_TRY_LINK([#include <tk.h>], [Tk_InitStubs(NULL, "", 0);],
+ tcl_cv_lib_tk_64=yes, tcl_cv_lib_tk_64=no)
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="$hold_'$v'"'
+ done])
+ ])
+ # remove 64-bit arch flags from CFLAGS et al. if configuration
+ # does not support 64-bit.
+ AS_IF([test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no], [
+ AC_MSG_NOTICE([Removing 64-bit architectures from compiler & linker flags])
+ for v in CFLAGS CPPFLAGS LDFLAGS; do
+ eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"'
+ done])
+ ])
+ ;;
+ OS/390-*)
+ CFLAGS_OPTIMIZE="" # Optimizer is buggy
+ AC_DEFINE(_OE_SOCKETS, 1, # needed in sys/socket.h
+ [Should OS/390 do the right thing with sockets?])
+ ;;
+ OSF1-V*)
+ # Digital OSF/1
+ SHLIB_CFLAGS=""
+ AS_IF([test "$SHARED_BUILD" = 1], [
+ SHLIB_LD='ld -shared -expect_unresolved "*"'
+ ], [
+ SHLIB_LD='ld -non_shared -expect_unresolved "*"'
+ ])
+ SHLIB_SUFFIX=".so"
+ AS_IF([test $doRpath = yes], [
+ CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}'])
+ AS_IF([test "$GCC" = yes], [CFLAGS="$CFLAGS -mieee"], [
+ CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee"])
+ # see pthread_intro(3) for pthread support on osf1, k.furukawa
+ AS_IF([test "${TCL_THREADS}" = 1], [
+ CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE"
+ CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64"
+ LIBS=`echo $LIBS | sed s/-lpthreads//`
+ AS_IF([test "$GCC" = yes], [
+ LIBS="$LIBS -lpthread -lmach -lexc"
+ ], [
+ CFLAGS="$CFLAGS -pthread"
+ LDFLAGS="$LDFLAGS -pthread"
+ ])
+ ])
+ ;;
+ QNX-6*)
+ # QNX RTP
+ # This may work for all QNX, but it was only reported for v6.
+ SHLIB_CFLAGS="-fPIC"
+ SHLIB_LD="ld -Bshareable -x"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SCO_SV-3.2*)
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_CFLAGS="-fPIC -melf"
+ LDFLAGS="$LDFLAGS -melf -Wl,-Bexport"
+ ], [
+ SHLIB_CFLAGS="-Kpic -belf"
+ LDFLAGS="$LDFLAGS -belf -Wl,-Bexport"
+ ])
+ SHLIB_LD="ld -G"
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ SunOS-5.[[0-6]])
+ # Careful to not let 5.10+ fall into this case
+
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_SUFFIX=".so"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ], [
+ SHLIB_LD="/usr/ccs/bin/ld -G -z text"
+ CC_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ ])
+ ;;
+ SunOS-5*)
+ # Note: If _REENTRANT isn't defined, then Solaris
+ # won't define thread-safe library routines.
+
+ AC_DEFINE(_REENTRANT, 1, [Do we want the reentrant OS API?])
+ AC_DEFINE(_POSIX_PTHREAD_SEMANTICS, 1,
+ [Do we really want to follow the standard? Yes we do!])
+
+ SHLIB_CFLAGS="-KPIC"
+
+ # Check to enable 64-bit flags for compiler/linker
+ AS_IF([test "$do64bit" = yes], [
+ arch=`isainfo`
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ AS_IF([test "$GCC" = yes], [
+ AS_IF([test "`${CC} -dumpversion | awk -F. '{print [$]1}'`" -lt 3], [
+ AC_MSG_WARN([64bit mode not supported with GCC < 3.2 on $system])
+ ], [
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64 -mcpu=v9"
+ LDFLAGS="$LDFLAGS -m64 -mcpu=v9"
+ SHLIB_CFLAGS="-fPIC"
+ ])
+ ], [
+ do64bit_ok=yes
+ AS_IF([test "$do64bitVIS" = yes], [
+ CFLAGS="$CFLAGS -xarch=v9a"
+ LDFLAGS_ARCH="-xarch=v9a"
+ ], [
+ CFLAGS="$CFLAGS -xarch=v9"
+ LDFLAGS_ARCH="-xarch=v9"
+ ])
+ # Solaris 64 uses this as well
+ #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64"
+ ])
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ AS_IF([test "$GCC" = yes], [
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ do64bit_ok=yes
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ AC_MSG_WARN([64bit mode not supported with GCC on $system]);;
+ esac
+ ], [
+ do64bit_ok=yes
+ case $system in
+ SunOS-5.1[[1-9]]*|SunOS-5.[[2-9]][[0-9]]*)
+ CFLAGS="$CFLAGS -m64"
+ LDFLAGS="$LDFLAGS -m64";;
+ *)
+ CFLAGS="$CFLAGS -xarch=amd64"
+ LDFLAGS="$LDFLAGS -xarch=amd64";;
+ esac
+ ])
+ ], [AC_MSG_WARN([64bit mode not supported for $arch])])])
+ ])
+
+ SHLIB_SUFFIX=".so"
+ AS_IF([test "$GCC" = yes], [
+ SHLIB_LD='${CC} -shared'
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS}
+ AS_IF([test "$do64bit_ok" = yes], [
+ AS_IF([test "$arch" = "sparcv9 sparc"], [
+ # We need to specify -static-libgcc or we need to
+ # add the path to the sparv9 libgcc.
+ # JH: static-libgcc is necessary for core Tcl, but may
+ # not be necessary for extensions.
+ SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc"
+ # for finding sparcv9 libgcc, get the regular libgcc
+ # path, remove so name and append 'sparcv9'
+ #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..."
+ #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir"
+ ], [AS_IF([test "$arch" = "amd64 i386"], [
+ # JH: static-libgcc is necessary for core Tcl, but may
+ # not be necessary for extensions.
+ SHLIB_LD="$SHLIB_LD -m64 -static-libgcc"
+ ])])
+ ])
+ ], [
+ case $system in
+ SunOS-5.[[1-9]][[0-9]]*)
+ # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS
+ SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';;
+ *)
+ SHLIB_LD='/usr/ccs/bin/ld -G -z text';;
+ esac
+ CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}'
+ LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}'
+ ])
+ ;;
+ UNIX_SV* | UnixWare-5*)
+ SHLIB_CFLAGS="-KPIC"
+ SHLIB_LD='${CC} -G'
+ SHLIB_LD_LIBS=""
+ SHLIB_SUFFIX=".so"
+ # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers
+ # that don't grok the -Bexport option. Test that it does.
+ AC_CACHE_CHECK([for ld accepts -Bexport flag], tcl_cv_ld_Bexport, [
+ hold_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ AC_TRY_LINK(, [int i;], tcl_cv_ld_Bexport=yes, tcl_cv_ld_Bexport=no)
+ LDFLAGS=$hold_ldflags])
+ AS_IF([test $tcl_cv_ld_Bexport = yes], [
+ LDFLAGS="$LDFLAGS -Wl,-Bexport"
+ ])
+ CC_SEARCH_FLAGS=""
+ LD_SEARCH_FLAGS=""
+ ;;
+ esac
+
+ AS_IF([test "$do64bit" = yes -a "$do64bit_ok" = no], [
+ AC_MSG_WARN([64bit support being disabled -- don't know magic for this platform])
+ ])
+
+dnl # Add any CPPFLAGS set in the environment to our CFLAGS, but delay doing so
+dnl # until the end of configure, as configure's compile and link tests use
+dnl # both CPPFLAGS and CFLAGS (unlike our compile and link) but configure's
+dnl # preprocessing tests use only CPPFLAGS.
+ AC_CONFIG_COMMANDS_PRE([CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS=""])
+
+ # Add in the arch flags late to ensure it wasn't removed.
+ # Not necessary in TEA, but this is aligned with core
+ LDFLAGS="$LDFLAGS $LDFLAGS_ARCH"
+
+ # If we're running gcc, then change the C flags for compiling shared
+ # libraries to the right flags for gcc, instead of those for the
+ # standard manufacturer compiler.
+
+ AS_IF([test "$GCC" = yes], [
+ case $system in
+ AIX-*) ;;
+ BSD/OS*) ;;
+ CYGWIN_*|MINGW32_*) ;;
+ IRIX*) ;;
+ NetBSD-*|FreeBSD-*|OpenBSD-*) ;;
+ Darwin-*) ;;
+ SCO_SV-3.2*) ;;
+ windows) ;;
+ *) SHLIB_CFLAGS="-fPIC" ;;
+ esac])
+
+ AS_IF([test "$tcl_cv_cc_visibility_hidden" != yes], [
+ AC_DEFINE(MODULE_SCOPE, [extern],
+ [No Compiler support for module scope symbols])
+ ])
+
+ AS_IF([test "$SHARED_LIB_SUFFIX" = ""], [
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}'])
+ AS_IF([test "$UNSHARED_LIB_SUFFIX" = ""], [
+ # TEA specific: use PACKAGE_VERSION instead of VERSION
+ UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a'])
+
+ if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then
+ AC_CACHE_CHECK(for SEH support in compiler,
+ tcl_cv_seh,
+ AC_TRY_RUN([
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+ int main(int argc, char** argv) {
+ int a, b = 0;
+ __try {
+ a = 666 / b;
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ return 0;
+ }
+ return 1;
+ }
+ ],
+ tcl_cv_seh=yes,
+ tcl_cv_seh=no,
+ tcl_cv_seh=no)
+ )
+ if test "$tcl_cv_seh" = "no" ; then
+ AC_DEFINE(HAVE_NO_SEH, 1,
+ [Defined when mingw does not support SEH])
+ fi
+
+ #
+ # Check to see if the excpt.h include file provided contains the
+ # definition for EXCEPTION_DISPOSITION; if not, which is the case
+ # with Cygwin's version as of 2002-04-10, define it to be int,
+ # sufficient for getting the current code to work.
+ #
+ AC_CACHE_CHECK(for EXCEPTION_DISPOSITION support in include files,
+ tcl_cv_eh_disposition,
+ AC_TRY_COMPILE([
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# undef WIN32_LEAN_AND_MEAN
+ ],[
+ EXCEPTION_DISPOSITION x;
+ ],
+ tcl_cv_eh_disposition=yes,
+ tcl_cv_eh_disposition=no)
+ )
+ if test "$tcl_cv_eh_disposition" = "no" ; then
+ AC_DEFINE(EXCEPTION_DISPOSITION, int,
+ [Defined when cygwin/mingw does not support EXCEPTION DISPOSITION])
+ fi
+
+ # Check to see if winnt.h defines CHAR, SHORT, and LONG
+ # even if VOID has already been #defined. The win32api
+ # used by mingw and cygwin is known to do this.
+
+ AC_CACHE_CHECK(for winnt.h that ignores VOID define,
+ tcl_cv_winnt_ignore_void,
+ AC_TRY_COMPILE([
+#define VOID void
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+ ], [
+ CHAR c;
+ SHORT s;
+ LONG l;
+ ],
+ tcl_cv_winnt_ignore_void=yes,
+ tcl_cv_winnt_ignore_void=no)
+ )
+ if test "$tcl_cv_winnt_ignore_void" = "yes" ; then
+ AC_DEFINE(HAVE_WINNT_IGNORE_VOID, 1,
+ [Defined when cygwin/mingw ignores VOID define in winnt.h])
+ fi
+ fi
+
+ # See if the compiler supports casting to a union type.
+ # This is used to stop gcc from printing a compiler
+ # warning when initializing a union member.
+
+ AC_CACHE_CHECK(for cast to union support,
+ tcl_cv_cast_to_union,
+ AC_TRY_COMPILE([],
+ [
+ union foo { int i; double d; };
+ union foo f = (union foo) (int) 0;
+ ],
+ tcl_cv_cast_to_union=yes,
+ tcl_cv_cast_to_union=no)
+ )
+ if test "$tcl_cv_cast_to_union" = "yes"; then
+ AC_DEFINE(HAVE_CAST_TO_UNION, 1,
+ [Defined when compiler supports casting to union type.])
+ fi
+
+ AC_SUBST(CFLAGS_DEBUG)
+ AC_SUBST(CFLAGS_OPTIMIZE)
+ AC_SUBST(CFLAGS_WARNING)
+
+ AC_SUBST(STLIB_LD)
+ AC_SUBST(SHLIB_LD)
+
+ AC_SUBST(SHLIB_LD_LIBS)
+ AC_SUBST(SHLIB_CFLAGS)
+
+ AC_SUBST(LD_LIBRARY_PATH_VAR)
+
+ # These must be called after we do the basic CFLAGS checks and
+ # verify any possible 64-bit or similar switches are necessary
+ TEA_TCL_EARLY_FLAGS
+ TEA_TCL_64BIT_FLAGS
+])
+
+#--------------------------------------------------------------------
+# TEA_SERIAL_PORT
+#
+# Determine which interface to use to talk to the serial port.
+# Note that #include lines must begin in leftmost column for
+# some compilers to recognize them as preprocessor directives,
+# and some build environments have stdin not pointing at a
+# pseudo-terminal (usually /dev/null instead.)
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines only one of the following vars:
+# HAVE_SYS_MODEM_H
+# USE_TERMIOS
+# USE_TERMIO
+# USE_SGTTY
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_SERIAL_PORT], [
+ AC_CHECK_HEADERS(sys/modem.h)
+ AC_CACHE_CHECK([termios vs. termio vs. sgtty], tcl_cv_api_serial, [
+ AC_TRY_RUN([
+#include <termios.h>
+
+int main() {
+ struct termios t;
+ if (tcgetattr(0, &t) == 0) {
+ cfsetospeed(&t, 0);
+ t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
+ return 0;
+ }
+ return 1;
+}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+ if test $tcl_cv_api_serial = no ; then
+ AC_TRY_RUN([
+#include <termio.h>
+
+int main() {
+ struct termio t;
+ if (ioctl(0, TCGETA, &t) == 0) {
+ t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
+ return 0;
+ }
+ return 1;
+}], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+ fi
+ if test $tcl_cv_api_serial = no ; then
+ AC_TRY_RUN([
+#include <sgtty.h>
+
+int main() {
+ struct sgttyb t;
+ if (ioctl(0, TIOCGETP, &t) == 0) {
+ t.sg_ospeed = 0;
+ t.sg_flags |= ODDP | EVENP | RAW;
+ return 0;
+ }
+ return 1;
+}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+ fi
+ if test $tcl_cv_api_serial = no ; then
+ AC_TRY_RUN([
+#include <termios.h>
+#include <errno.h>
+
+int main() {
+ struct termios t;
+ if (tcgetattr(0, &t) == 0
+ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+ cfsetospeed(&t, 0);
+ t.c_cflag |= PARENB | PARODD | CSIZE | CSTOPB;
+ return 0;
+ }
+ return 1;
+}], tcl_cv_api_serial=termios, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+ fi
+ if test $tcl_cv_api_serial = no; then
+ AC_TRY_RUN([
+#include <termio.h>
+#include <errno.h>
+
+int main() {
+ struct termio t;
+ if (ioctl(0, TCGETA, &t) == 0
+ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+ t.c_cflag |= CBAUD | PARENB | PARODD | CSIZE | CSTOPB;
+ return 0;
+ }
+ return 1;
+ }], tcl_cv_api_serial=termio, tcl_cv_api_serial=no, tcl_cv_api_serial=no)
+ fi
+ if test $tcl_cv_api_serial = no; then
+ AC_TRY_RUN([
+#include <sgtty.h>
+#include <errno.h>
+
+int main() {
+ struct sgttyb t;
+ if (ioctl(0, TIOCGETP, &t) == 0
+ || errno == ENOTTY || errno == ENXIO || errno == EINVAL) {
+ t.sg_ospeed = 0;
+ t.sg_flags |= ODDP | EVENP | RAW;
+ return 0;
+ }
+ return 1;
+}], tcl_cv_api_serial=sgtty, tcl_cv_api_serial=none, tcl_cv_api_serial=none)
+ fi])
+ case $tcl_cv_api_serial in
+ termios) AC_DEFINE(USE_TERMIOS, 1, [Use the termios API for serial lines]);;
+ termio) AC_DEFINE(USE_TERMIO, 1, [Use the termio API for serial lines]);;
+ sgtty) AC_DEFINE(USE_SGTTY, 1, [Use the sgtty API for serial lines]);;
+ esac
+])
+
+#--------------------------------------------------------------------
+# TEA_MISSING_POSIX_HEADERS
+#
+# Supply substitutes for missing POSIX header files. Special
+# notes:
+# - stdlib.h doesn't define strtol, strtoul, or
+# strtod in some versions of SunOS
+# - some versions of string.h don't declare procedures such
+# as strstr
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# NO_DIRENT_H
+# NO_ERRNO_H
+# NO_VALUES_H
+# HAVE_LIMITS_H or NO_LIMITS_H
+# NO_STDLIB_H
+# NO_STRING_H
+# NO_SYS_WAIT_H
+# NO_DLFCN_H
+# HAVE_SYS_PARAM_H
+#
+# HAVE_STRING_H ?
+#
+# tkUnixPort.h checks for HAVE_LIMITS_H, so do both HAVE and
+# CHECK on limits.h
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_MISSING_POSIX_HEADERS], [
+ AC_CACHE_CHECK([dirent.h], tcl_cv_dirent_h, [
+ AC_TRY_LINK([#include <sys/types.h>
+#include <dirent.h>], [
+#ifndef _POSIX_SOURCE
+# ifdef __Lynx__
+ /*
+ * Generate compilation error to make the test fail: Lynx headers
+ * are only valid if really in the POSIX environment.
+ */
+
+ missing_procedure();
+# endif
+#endif
+DIR *d;
+struct dirent *entryPtr;
+char *p;
+d = opendir("foobar");
+entryPtr = readdir(d);
+p = entryPtr->d_name;
+closedir(d);
+], tcl_cv_dirent_h=yes, tcl_cv_dirent_h=no)])
+
+ if test $tcl_cv_dirent_h = no; then
+ AC_DEFINE(NO_DIRENT_H, 1, [Do we have <dirent.h>?])
+ fi
+
+ # TEA specific:
+ AC_CHECK_HEADER(errno.h, , [AC_DEFINE(NO_ERRNO_H, 1, [Do we have <errno.h>?])])
+ AC_CHECK_HEADER(float.h, , [AC_DEFINE(NO_FLOAT_H, 1, [Do we have <float.h>?])])
+ AC_CHECK_HEADER(values.h, , [AC_DEFINE(NO_VALUES_H, 1, [Do we have <values.h>?])])
+ AC_CHECK_HEADER(limits.h,
+ [AC_DEFINE(HAVE_LIMITS_H, 1, [Do we have <limits.h>?])],
+ [AC_DEFINE(NO_LIMITS_H, 1, [Do we have <limits.h>?])])
+ AC_CHECK_HEADER(stdlib.h, tcl_ok=1, tcl_ok=0)
+ AC_EGREP_HEADER(strtol, stdlib.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strtoul, stdlib.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strtod, stdlib.h, , tcl_ok=0)
+ if test $tcl_ok = 0; then
+ AC_DEFINE(NO_STDLIB_H, 1, [Do we have <stdlib.h>?])
+ fi
+ AC_CHECK_HEADER(string.h, tcl_ok=1, tcl_ok=0)
+ AC_EGREP_HEADER(strstr, string.h, , tcl_ok=0)
+ AC_EGREP_HEADER(strerror, string.h, , tcl_ok=0)
+
+ # See also memmove check below for a place where NO_STRING_H can be
+ # set and why.
+
+ if test $tcl_ok = 0; then
+ AC_DEFINE(NO_STRING_H, 1, [Do we have <string.h>?])
+ fi
+
+ AC_CHECK_HEADER(sys/wait.h, , [AC_DEFINE(NO_SYS_WAIT_H, 1, [Do we have <sys/wait.h>?])])
+ AC_CHECK_HEADER(dlfcn.h, , [AC_DEFINE(NO_DLFCN_H, 1, [Do we have <dlfcn.h>?])])
+
+ # OS/390 lacks sys/param.h (and doesn't need it, by chance).
+ AC_HAVE_HEADERS(sys/param.h)
+])
+
+#--------------------------------------------------------------------
+# TEA_PATH_X
+#
+# Locate the X11 header files and the X11 library archive. Try
+# the ac_path_x macro first, but if it doesn't find the X stuff
+# (e.g. because there's no xmkmf program) then check through
+# a list of possible directories. Under some conditions the
+# autoconf macro will return an include directory that contains
+# no include files, so double-check its result just to be safe.
+#
+# This should be called after TEA_CONFIG_CFLAGS as setting the
+# LIBS line can confuse some configure macro magic.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets the following vars:
+# XINCLUDES
+# XLIBSW
+# PKG_LIBS (appends to)
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_X], [
+ if test "${TEA_WINDOWINGSYSTEM}" = "x11" ; then
+ TEA_PATH_UNIX_X
+ fi
+])
+
+AC_DEFUN([TEA_PATH_UNIX_X], [
+ AC_PATH_X
+ not_really_there=""
+ if test "$no_x" = ""; then
+ if test "$x_includes" = ""; then
+ AC_TRY_CPP([#include <X11/Xlib.h>], , not_really_there="yes")
+ else
+ if test ! -r $x_includes/X11/Xlib.h; then
+ not_really_there="yes"
+ fi
+ fi
+ fi
+ if test "$no_x" = "yes" -o "$not_really_there" = "yes"; then
+ AC_MSG_CHECKING([for X11 header files])
+ found_xincludes="no"
+ AC_TRY_CPP([#include <X11/Xlib.h>], found_xincludes="yes", found_xincludes="no")
+ if test "$found_xincludes" = "no"; then
+ dirs="/usr/unsupported/include /usr/local/include /usr/X386/include /usr/X11R6/include /usr/X11R5/include /usr/include/X11R5 /usr/include/X11R4 /usr/openwin/include /usr/X11/include /usr/sww/include"
+ for i in $dirs ; do
+ if test -r $i/X11/Xlib.h; then
+ AC_MSG_RESULT([$i])
+ XINCLUDES=" -I$i"
+ found_xincludes="yes"
+ break
+ fi
+ done
+ fi
+ else
+ if test "$x_includes" != ""; then
+ XINCLUDES="-I$x_includes"
+ found_xincludes="yes"
+ fi
+ fi
+ if test "$found_xincludes" = "no"; then
+ AC_MSG_RESULT([couldn't find any!])
+ fi
+
+ if test "$no_x" = yes; then
+ AC_MSG_CHECKING([for X11 libraries])
+ XLIBSW=nope
+ dirs="/usr/unsupported/lib /usr/local/lib /usr/X386/lib /usr/X11R6/lib /usr/X11R5/lib /usr/lib/X11R5 /usr/lib/X11R4 /usr/openwin/lib /usr/X11/lib /usr/sww/X11/lib"
+ for i in $dirs ; do
+ if test -r $i/libX11.a -o -r $i/libX11.so -o -r $i/libX11.sl -o -r $i/libX11.dylib; then
+ AC_MSG_RESULT([$i])
+ XLIBSW="-L$i -lX11"
+ x_libraries="$i"
+ break
+ fi
+ done
+ else
+ if test "$x_libraries" = ""; then
+ XLIBSW=-lX11
+ else
+ XLIBSW="-L$x_libraries -lX11"
+ fi
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_CHECK_LIB(Xwindow, XCreateWindow, XLIBSW=-lXwindow)
+ fi
+ if test "$XLIBSW" = nope ; then
+ AC_MSG_RESULT([could not find any! Using -lX11.])
+ XLIBSW=-lX11
+ fi
+ # TEA specific:
+ if test x"${XLIBSW}" != x ; then
+ PKG_LIBS="${PKG_LIBS} ${XLIBSW}"
+ fi
+])
+
+#--------------------------------------------------------------------
+# TEA_BLOCKING_STYLE
+#
+# The statements below check for systems where POSIX-style
+# non-blocking I/O (O_NONBLOCK) doesn't work or is unimplemented.
+# On these systems (mostly older ones), use the old BSD-style
+# FIONBIO approach instead.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# HAVE_SYS_IOCTL_H
+# HAVE_SYS_FILIO_H
+# USE_FIONBIO
+# O_NONBLOCK
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_BLOCKING_STYLE], [
+ AC_CHECK_HEADERS(sys/ioctl.h)
+ AC_CHECK_HEADERS(sys/filio.h)
+ TEA_CONFIG_SYSTEM
+ AC_MSG_CHECKING([FIONBIO vs. O_NONBLOCK for nonblocking I/O])
+ case $system in
+ OSF*)
+ AC_DEFINE(USE_FIONBIO, 1, [Should we use FIONBIO?])
+ AC_MSG_RESULT([FIONBIO])
+ ;;
+ *)
+ AC_MSG_RESULT([O_NONBLOCK])
+ ;;
+ esac
+])
+
+#--------------------------------------------------------------------
+# TEA_TIME_HANDLER
+#
+# Checks how the system deals with time.h, what time structures
+# are used on the system, and what fields the structures have.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines some of the following vars:
+# USE_DELTA_FOR_TZ
+# HAVE_TM_GMTOFF
+# HAVE_TM_TZADJ
+# HAVE_TIMEZONE_VAR
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_TIME_HANDLER], [
+ AC_CHECK_HEADERS(sys/time.h)
+ AC_HEADER_TIME
+ AC_STRUCT_TIMEZONE
+
+ AC_CHECK_FUNCS(gmtime_r localtime_r)
+
+ AC_CACHE_CHECK([tm_tzadj in struct tm], tcl_cv_member_tm_tzadj, [
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_tzadj;],
+ tcl_cv_member_tm_tzadj=yes, tcl_cv_member_tm_tzadj=no)])
+ if test $tcl_cv_member_tm_tzadj = yes ; then
+ AC_DEFINE(HAVE_TM_TZADJ, 1, [Should we use the tm_tzadj field of struct tm?])
+ fi
+
+ AC_CACHE_CHECK([tm_gmtoff in struct tm], tcl_cv_member_tm_gmtoff, [
+ AC_TRY_COMPILE([#include <time.h>], [struct tm tm; tm.tm_gmtoff;],
+ tcl_cv_member_tm_gmtoff=yes, tcl_cv_member_tm_gmtoff=no)])
+ if test $tcl_cv_member_tm_gmtoff = yes ; then
+ AC_DEFINE(HAVE_TM_GMTOFF, 1, [Should we use the tm_gmtoff field of struct tm?])
+ fi
+
+ #
+ # Its important to include time.h in this check, as some systems
+ # (like convex) have timezone functions, etc.
+ #
+ AC_CACHE_CHECK([long timezone variable], tcl_cv_timezone_long, [
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern long timezone;
+ timezone += 1;
+ exit (0);],
+ tcl_cv_timezone_long=yes, tcl_cv_timezone_long=no)])
+ if test $tcl_cv_timezone_long = yes ; then
+ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+ else
+ #
+ # On some systems (eg IRIX 6.2), timezone is a time_t and not a long.
+ #
+ AC_CACHE_CHECK([time_t timezone variable], tcl_cv_timezone_time, [
+ AC_TRY_COMPILE([#include <time.h>],
+ [extern time_t timezone;
+ timezone += 1;
+ exit (0);],
+ tcl_cv_timezone_time=yes, tcl_cv_timezone_time=no)])
+ if test $tcl_cv_timezone_time = yes ; then
+ AC_DEFINE(HAVE_TIMEZONE_VAR, 1, [Should we use the global timezone variable?])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# TEA_BUGGY_STRTOD
+#
+# Under Solaris 2.4, strtod returns the wrong value for the
+# terminating character under some conditions. Check for this
+# and if the problem exists use a substitute procedure
+# "fixstrtod" (provided by Tcl) that corrects the error.
+# Also, on Compaq's Tru64 Unix 5.0,
+# strtod(" ") returns 0.0 instead of a failure to convert.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Might defines some of the following vars:
+# strtod (=fixstrtod)
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_BUGGY_STRTOD], [
+ AC_CHECK_FUNC(strtod, tcl_strtod=1, tcl_strtod=0)
+ if test "$tcl_strtod" = 1; then
+ AC_CACHE_CHECK([for Solaris2.4/Tru64 strtod bugs], tcl_cv_strtod_buggy,[
+ AC_TRY_RUN([
+ extern double strtod();
+ int main() {
+ char *infString="Inf", *nanString="NaN", *spaceString=" ";
+ char *term;
+ double value;
+ value = strtod(infString, &term);
+ if ((term != infString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(nanString, &term);
+ if ((term != nanString) && (term[-1] == 0)) {
+ exit(1);
+ }
+ value = strtod(spaceString, &term);
+ if (term == (spaceString+1)) {
+ exit(1);
+ }
+ exit(0);
+ }], tcl_cv_strtod_buggy=ok, tcl_cv_strtod_buggy=buggy,
+ tcl_cv_strtod_buggy=buggy)])
+ if test "$tcl_cv_strtod_buggy" = buggy; then
+ AC_LIBOBJ([fixstrtod])
+ USE_COMPAT=1
+ AC_DEFINE(strtod, fixstrtod, [Do we want to use the strtod() in compat?])
+ fi
+ fi
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_LINK_LIBS
+#
+# Search for the libraries needed to link the Tcl shell.
+# Things like the math library (-lm) and socket stuff (-lsocket vs.
+# -lnsl) are dealt with here.
+#
+# Arguments:
+# Requires the following vars to be set in the Makefile:
+# DL_LIBS (not in TEA, only needed in core)
+# LIBS
+# MATH_LIBS
+#
+# Results:
+#
+# Substitutes the following vars:
+# TCL_LIBS
+# MATH_LIBS
+#
+# Might append to the following vars:
+# LIBS
+#
+# Might define the following vars:
+# HAVE_NET_ERRNO_H
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_TCL_LINK_LIBS], [
+ #--------------------------------------------------------------------
+ # On a few very rare systems, all of the libm.a stuff is
+ # already in libc.a. Set compiler flags accordingly.
+ # Also, Linux requires the "ieee" library for math to work
+ # right (and it must appear before "-lm").
+ #--------------------------------------------------------------------
+
+ AC_CHECK_FUNC(sin, MATH_LIBS="", MATH_LIBS="-lm")
+ AC_CHECK_LIB(ieee, main, [MATH_LIBS="-lieee $MATH_LIBS"])
+
+ #--------------------------------------------------------------------
+ # Interactive UNIX requires -linet instead of -lsocket, plus it
+ # needs net/errno.h to define the socket-related error codes.
+ #--------------------------------------------------------------------
+
+ AC_CHECK_LIB(inet, main, [LIBS="$LIBS -linet"])
+ AC_CHECK_HEADER(net/errno.h, [
+ AC_DEFINE(HAVE_NET_ERRNO_H, 1, [Do we have <net/errno.h>?])])
+
+ #--------------------------------------------------------------------
+ # Check for the existence of the -lsocket and -lnsl libraries.
+ # The order here is important, so that they end up in the right
+ # order in the command line generated by make. Here are some
+ # special considerations:
+ # 1. Use "connect" and "accept" to check for -lsocket, and
+ # "gethostbyname" to check for -lnsl.
+ # 2. Use each function name only once: can't redo a check because
+ # autoconf caches the results of the last check and won't redo it.
+ # 3. Use -lnsl and -lsocket only if they supply procedures that
+ # aren't already present in the normal libraries. This is because
+ # IRIX 5.2 has libraries, but they aren't needed and they're
+ # bogus: they goof up name resolution if used.
+ # 4. On some SVR4 systems, can't use -lsocket without -lnsl too.
+ # To get around this problem, check for both libraries together
+ # if -lsocket doesn't work by itself.
+ #--------------------------------------------------------------------
+
+ tcl_checkBoth=0
+ AC_CHECK_FUNC(connect, tcl_checkSocket=0, tcl_checkSocket=1)
+ if test "$tcl_checkSocket" = 1; then
+ AC_CHECK_FUNC(setsockopt, , [AC_CHECK_LIB(socket, setsockopt,
+ LIBS="$LIBS -lsocket", tcl_checkBoth=1)])
+ fi
+ if test "$tcl_checkBoth" = 1; then
+ tk_oldLibs=$LIBS
+ LIBS="$LIBS -lsocket -lnsl"
+ AC_CHECK_FUNC(accept, tcl_checkNsl=0, [LIBS=$tk_oldLibs])
+ fi
+ AC_CHECK_FUNC(gethostbyname, , [AC_CHECK_LIB(nsl, gethostbyname,
+ [LIBS="$LIBS -lnsl"])])
+
+ # TEA specific: Don't perform the eval of the libraries here because
+ # DL_LIBS won't be set until we call TEA_CONFIG_CFLAGS
+
+ TCL_LIBS='${DL_LIBS} ${LIBS} ${MATH_LIBS}'
+ AC_SUBST(TCL_LIBS)
+ AC_SUBST(MATH_LIBS)
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_EARLY_FLAGS
+#
+# Check for what flags are needed to be passed so the correct OS
+# features are available.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# _ISOC99_SOURCE
+# _LARGEFILE64_SOURCE
+# _LARGEFILE_SOURCE64
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_TCL_EARLY_FLAG],[
+ AC_CACHE_VAL([tcl_cv_flag_]translit($1,[A-Z],[a-z]),
+ AC_TRY_COMPILE([$2], $3, [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no,
+ AC_TRY_COMPILE([[#define ]$1[ 1
+]$2], $3,
+ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=yes,
+ [tcl_cv_flag_]translit($1,[A-Z],[a-z])=no)))
+ if test ["x${tcl_cv_flag_]translit($1,[A-Z],[a-z])[}" = "xyes"] ; then
+ AC_DEFINE($1, 1, [Add the ]$1[ flag when building])
+ tcl_flags="$tcl_flags $1"
+ fi
+])
+
+AC_DEFUN([TEA_TCL_EARLY_FLAGS],[
+ AC_MSG_CHECKING([for required early compiler flags])
+ tcl_flags=""
+ TEA_TCL_EARLY_FLAG(_ISOC99_SOURCE,[#include <stdlib.h>],
+ [char *p = (char *)strtoll; char *q = (char *)strtoull;])
+ TEA_TCL_EARLY_FLAG(_LARGEFILE64_SOURCE,[#include <sys/stat.h>],
+ [struct stat64 buf; int i = stat64("/", &buf);])
+ TEA_TCL_EARLY_FLAG(_LARGEFILE_SOURCE64,[#include <sys/stat.h>],
+ [char *p = (char *)open64;])
+ if test "x${tcl_flags}" = "x" ; then
+ AC_MSG_RESULT([none])
+ else
+ AC_MSG_RESULT([${tcl_flags}])
+ fi
+])
+
+#--------------------------------------------------------------------
+# TEA_TCL_64BIT_FLAGS
+#
+# Check for what is defined in the way of 64-bit features.
+#
+# Arguments:
+# None
+#
+# Results:
+#
+# Might define the following vars:
+# TCL_WIDE_INT_IS_LONG
+# TCL_WIDE_INT_TYPE
+# HAVE_STRUCT_DIRENT64
+# HAVE_STRUCT_STAT64
+# HAVE_TYPE_OFF64_T
+#--------------------------------------------------------------------
+
+AC_DEFUN([TEA_TCL_64BIT_FLAGS], [
+ AC_MSG_CHECKING([for 64-bit integer type])
+ AC_CACHE_VAL(tcl_cv_type_64bit,[
+ tcl_cv_type_64bit=none
+ # See if the compiler knows natively about __int64
+ AC_TRY_COMPILE(,[__int64 value = (__int64) 0;],
+ tcl_type_64bit=__int64, tcl_type_64bit="long long")
+ # See if we should use long anyway Note that we substitute in the
+ # type that is our current guess for a 64-bit type inside this check
+ # program, so it should be modified only carefully...
+ AC_TRY_COMPILE(,[switch (0) {
+ case 1: case (sizeof(]${tcl_type_64bit}[)==sizeof(long)): ;
+ }],tcl_cv_type_64bit=${tcl_type_64bit})])
+ if test "${tcl_cv_type_64bit}" = none ; then
+ AC_DEFINE(TCL_WIDE_INT_IS_LONG, 1, [Are wide integers to be implemented with C 'long's?])
+ AC_MSG_RESULT([using long])
+ elif test "${tcl_cv_type_64bit}" = "__int64" \
+ -a "${TEA_PLATFORM}" = "windows" ; then
+ # TEA specific: We actually want to use the default tcl.h checks in
+ # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER*
+ AC_MSG_RESULT([using Tcl header defaults])
+ else
+ AC_DEFINE_UNQUOTED(TCL_WIDE_INT_TYPE,${tcl_cv_type_64bit},
+ [What type should be used to define wide integers?])
+ AC_MSG_RESULT([${tcl_cv_type_64bit}])
+
+ # Now check for auxiliary declarations
+ AC_CACHE_CHECK([for struct dirent64], tcl_cv_struct_dirent64,[
+ AC_TRY_COMPILE([#include <sys/types.h>
+#include <dirent.h>],[struct dirent64 p;],
+ tcl_cv_struct_dirent64=yes,tcl_cv_struct_dirent64=no)])
+ if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then
+ AC_DEFINE(HAVE_STRUCT_DIRENT64, 1, [Is 'struct dirent64' in <sys/types.h>?])
+ fi
+
+ AC_CACHE_CHECK([for struct stat64], tcl_cv_struct_stat64,[
+ AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat64 p;
+],
+ tcl_cv_struct_stat64=yes,tcl_cv_struct_stat64=no)])
+ if test "x${tcl_cv_struct_stat64}" = "xyes" ; then
+ AC_DEFINE(HAVE_STRUCT_STAT64, 1, [Is 'struct stat64' in <sys/stat.h>?])
+ fi
+
+ AC_CHECK_FUNCS(open64 lseek64)
+ AC_MSG_CHECKING([for off64_t])
+ AC_CACHE_VAL(tcl_cv_type_off64_t,[
+ AC_TRY_COMPILE([#include <sys/types.h>],[off64_t offset;
+],
+ tcl_cv_type_off64_t=yes,tcl_cv_type_off64_t=no)])
+ dnl Define HAVE_TYPE_OFF64_T only when the off64_t type and the
+ dnl functions lseek64 and open64 are defined.
+ if test "x${tcl_cv_type_off64_t}" = "xyes" && \
+ test "x${ac_cv_func_lseek64}" = "xyes" && \
+ test "x${ac_cv_func_open64}" = "xyes" ; then
+ AC_DEFINE(HAVE_TYPE_OFF64_T, 1, [Is off64_t in <sys/types.h>?])
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ fi
+])
+
+##
+## Here ends the standard Tcl configuration bits and starts the
+## TEA specific functions
+##
+
+#------------------------------------------------------------------------
+# TEA_INIT --
+#
+# Init various Tcl Extension Architecture (TEA) variables.
+# This should be the first called TEA_* macro.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Defines and substs the following vars:
+# CYGPATH
+# EXEEXT
+# Defines only:
+# TEA_VERSION
+# TEA_INITED
+# TEA_PLATFORM (windows or unix)
+#
+# "cygpath" is used on windows to generate native path names for include
+# files. These variables should only be used with the compiler and linker
+# since they generate native path names.
+#
+# EXEEXT
+# Select the executable extension based on the host type. This
+# is a lightweight replacement for AC_EXEEXT that doesn't require
+# a compiler.
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_INIT], [
+ # TEA extensions pass this us the version of TEA they think they
+ # are compatible with.
+ TEA_VERSION="3.9"
+
+ AC_MSG_CHECKING([for correct TEA configuration])
+ if test x"${PACKAGE_NAME}" = x ; then
+ AC_MSG_ERROR([
+The PACKAGE_NAME variable must be defined by your TEA configure.in])
+ fi
+ if test x"$1" = x ; then
+ AC_MSG_ERROR([
+TEA version not specified.])
+ elif test "$1" != "${TEA_VERSION}" ; then
+ AC_MSG_RESULT([warning: requested TEA version "$1", have "${TEA_VERSION}"])
+ else
+ AC_MSG_RESULT([ok (TEA ${TEA_VERSION})])
+ fi
+
+ # If the user did not set CFLAGS, set it now to keep macros
+ # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2".
+ if test "${CFLAGS+set}" != "set" ; then
+ CFLAGS=""
+ fi
+
+ case "`uname -s`" in
+ *win32*|*WIN32*|*MINGW32_*)
+ AC_CHECK_PROG(CYGPATH, cygpath, cygpath -w, echo)
+ EXEEXT=".exe"
+ TEA_PLATFORM="windows"
+ ;;
+ *CYGWIN_*)
+ CYGPATH=echo
+ EXEEXT=".exe"
+ # TEA_PLATFORM is determined later in LOAD_TCLCONFIG
+ ;;
+ *)
+ CYGPATH=echo
+ # Maybe we are cross-compiling....
+ case ${host_alias} in
+ *mingw32*)
+ EXEEXT=".exe"
+ TEA_PLATFORM="windows"
+ ;;
+ *)
+ EXEEXT=""
+ TEA_PLATFORM="unix"
+ ;;
+ esac
+ ;;
+ esac
+
+ # Check if exec_prefix is set. If not use fall back to prefix.
+ # Note when adjusted, so that TEA_PREFIX can correct for this.
+ # This is needed for recursive configures, since autoconf propagates
+ # $prefix, but not $exec_prefix (doh!).
+ if test x$exec_prefix = xNONE ; then
+ exec_prefix_default=yes
+ exec_prefix=$prefix
+ fi
+
+ AC_MSG_NOTICE([configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}])
+
+ AC_SUBST(EXEEXT)
+ AC_SUBST(CYGPATH)
+
+ # This package name must be replaced statically for AC_SUBST to work
+ AC_SUBST(PKG_LIB_FILE)
+ # Substitute STUB_LIB_FILE in case package creates a stub library too.
+ AC_SUBST(PKG_STUB_LIB_FILE)
+
+ # We AC_SUBST these here to ensure they are subst'ed,
+ # in case the user doesn't call TEA_ADD_...
+ AC_SUBST(PKG_STUB_SOURCES)
+ AC_SUBST(PKG_STUB_OBJECTS)
+ AC_SUBST(PKG_TCL_SOURCES)
+ AC_SUBST(PKG_HEADERS)
+ AC_SUBST(PKG_INCLUDES)
+ AC_SUBST(PKG_LIBS)
+ AC_SUBST(PKG_CFLAGS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_SOURCES --
+#
+# Specify one or more source files. Users should check for
+# the right platform before adding to their list.
+# It is not important to specify the directory, as long as it is
+# in the generic, win or unix subdirectory of $(srcdir).
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_SOURCES
+# PKG_OBJECTS
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_SOURCES], [
+ vars="$@"
+ for i in $vars; do
+ case $i in
+ [\$]*)
+ # allow $-var names
+ PKG_SOURCES="$PKG_SOURCES $i"
+ PKG_OBJECTS="$PKG_OBJECTS $i"
+ ;;
+ *)
+ # check for existence - allows for generic/win/unix VPATH
+ # To add more dirs here (like 'src'), you have to update VPATH
+ # in Makefile.in as well
+ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+ -a ! -f "${srcdir}/macosx/$i" \
+ ; then
+ AC_MSG_ERROR([could not find source file '$i'])
+ fi
+ PKG_SOURCES="$PKG_SOURCES $i"
+ # this assumes it is in a VPATH dir
+ i=`basename $i`
+ # handle user calling this before or after TEA_SETUP_COMPILER
+ if test x"${OBJEXT}" != x ; then
+ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
+ else
+ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
+ fi
+ PKG_OBJECTS="$PKG_OBJECTS $j"
+ ;;
+ esac
+ done
+ AC_SUBST(PKG_SOURCES)
+ AC_SUBST(PKG_OBJECTS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_STUB_SOURCES --
+#
+# Specify one or more source files. Users should check for
+# the right platform before adding to their list.
+# It is not important to specify the directory, as long as it is
+# in the generic, win or unix subdirectory of $(srcdir).
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_STUB_SOURCES
+# PKG_STUB_OBJECTS
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_STUB_SOURCES], [
+ vars="$@"
+ for i in $vars; do
+ # check for existence - allows for generic/win/unix VPATH
+ if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \
+ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \
+ -a ! -f "${srcdir}/macosx/$i" \
+ ; then
+ AC_MSG_ERROR([could not find stub source file '$i'])
+ fi
+ PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i"
+ # this assumes it is in a VPATH dir
+ i=`basename $i`
+ # handle user calling this before or after TEA_SETUP_COMPILER
+ if test x"${OBJEXT}" != x ; then
+ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.${OBJEXT}"
+ else
+ j="`echo $i | sed -e 's/\.[[^.]]*$//'`.\${OBJEXT}"
+ fi
+ PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j"
+ done
+ AC_SUBST(PKG_STUB_SOURCES)
+ AC_SUBST(PKG_STUB_OBJECTS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_TCL_SOURCES --
+#
+# Specify one or more Tcl source files. These should be platform
+# independent runtime files.
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_TCL_SOURCES
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_TCL_SOURCES], [
+ vars="$@"
+ for i in $vars; do
+ # check for existence, be strict because it is installed
+ if test ! -f "${srcdir}/$i" ; then
+ AC_MSG_ERROR([could not find tcl source file '${srcdir}/$i'])
+ fi
+ PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i"
+ done
+ AC_SUBST(PKG_TCL_SOURCES)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_HEADERS --
+#
+# Specify one or more source headers. Users should check for
+# the right platform before adding to their list.
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_HEADERS
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_HEADERS], [
+ vars="$@"
+ for i in $vars; do
+ # check for existence, be strict because it is installed
+ if test ! -f "${srcdir}/$i" ; then
+ AC_MSG_ERROR([could not find header file '${srcdir}/$i'])
+ fi
+ PKG_HEADERS="$PKG_HEADERS $i"
+ done
+ AC_SUBST(PKG_HEADERS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_INCLUDES --
+#
+# Specify one or more include dirs. Users should check for
+# the right platform before adding to their list.
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_INCLUDES
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_INCLUDES], [
+ vars="$@"
+ for i in $vars; do
+ PKG_INCLUDES="$PKG_INCLUDES $i"
+ done
+ AC_SUBST(PKG_INCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_LIBS --
+#
+# Specify one or more libraries. Users should check for
+# the right platform before adding to their list. For Windows,
+# libraries provided in "foo.lib" format will be converted to
+# "-lfoo" when using GCC (mingw).
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_LIBS
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_LIBS], [
+ vars="$@"
+ for i in $vars; do
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then
+ # Convert foo.lib to -lfoo for GCC. No-op if not *.lib
+ i=`echo "$i" | sed -e 's/^\([[^-]].*\)\.lib[$]/-l\1/i'`
+ fi
+ PKG_LIBS="$PKG_LIBS $i"
+ done
+ AC_SUBST(PKG_LIBS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_CFLAGS --
+#
+# Specify one or more CFLAGS. Users should check for
+# the right platform before adding to their list.
+#
+# Arguments:
+# one or more file names
+#
+# Results:
+#
+# Defines and substs the following vars:
+# PKG_CFLAGS
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_CFLAGS], [
+ PKG_CFLAGS="$PKG_CFLAGS $@"
+ AC_SUBST(PKG_CFLAGS)
+])
+
+#------------------------------------------------------------------------
+# TEA_ADD_CLEANFILES --
+#
+# Specify one or more CLEANFILES.
+#
+# Arguments:
+# one or more file names to clean target
+#
+# Results:
+#
+# Appends to CLEANFILES, already defined for subst in LOAD_TCLCONFIG
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_ADD_CLEANFILES], [
+ CLEANFILES="$CLEANFILES $@"
+])
+
+#------------------------------------------------------------------------
+# TEA_PREFIX --
+#
+# Handle the --prefix=... option by defaulting to what Tcl gave
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# If --prefix or --exec-prefix was not specified, $prefix and
+# $exec_prefix will be set to the values given to Tcl when it was
+# configured.
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_PREFIX], [
+ if test "${prefix}" = "NONE"; then
+ prefix_default=yes
+ if test x"${TCL_PREFIX}" != x; then
+ AC_MSG_NOTICE([--prefix defaulting to TCL_PREFIX ${TCL_PREFIX}])
+ prefix=${TCL_PREFIX}
+ else
+ AC_MSG_NOTICE([--prefix defaulting to /usr/local])
+ prefix=/usr/local
+ fi
+ fi
+ if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \
+ -o x"${exec_prefix_default}" = x"yes" ; then
+ if test x"${TCL_EXEC_PREFIX}" != x; then
+ AC_MSG_NOTICE([--exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}])
+ exec_prefix=${TCL_EXEC_PREFIX}
+ else
+ AC_MSG_NOTICE([--exec-prefix defaulting to ${prefix}])
+ exec_prefix=$prefix
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_SETUP_COMPILER_CC --
+#
+# Do compiler checks the way we want. This is just a replacement
+# for AC_PROG_CC in TEA configure.in files to make them cleaner.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets up CC var and other standard bits we need to make executables.
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_SETUP_COMPILER_CC], [
+ # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE)
+ # in this macro, they need to go into TEA_SETUP_COMPILER instead.
+
+ AC_PROG_CC
+ AC_PROG_CPP
+
+ INSTALL="\$(SHELL) \$(srcdir)/tclconfig/install-sh -c"
+ AC_SUBST(INSTALL)
+
+ #--------------------------------------------------------------------
+ # Checks to see if the make program sets the $MAKE variable.
+ #--------------------------------------------------------------------
+
+ AC_PROG_MAKE_SET
+
+ #--------------------------------------------------------------------
+ # Find ranlib
+ #--------------------------------------------------------------------
+
+ AC_CHECK_TOOL(RANLIB, ranlib)
+
+ #--------------------------------------------------------------------
+ # Determines the correct binary file extension (.o, .obj, .exe etc.)
+ #--------------------------------------------------------------------
+
+ AC_OBJEXT
+ AC_EXEEXT
+])
+
+#------------------------------------------------------------------------
+# TEA_SETUP_COMPILER --
+#
+# Do compiler checks that use the compiler. This must go after
+# TEA_SETUP_COMPILER_CC, which does the actual compiler check.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Sets up CC var and other standard bits we need to make executables.
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_SETUP_COMPILER], [
+ # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here.
+ AC_REQUIRE([TEA_SETUP_COMPILER_CC])
+
+ #------------------------------------------------------------------------
+ # If we're using GCC, see if the compiler understands -pipe. If so, use it.
+ # It makes compiling go faster. (This is only a performance feature.)
+ #------------------------------------------------------------------------
+
+ if test -z "$no_pipe" -a -n "$GCC"; then
+ AC_CACHE_CHECK([if the compiler understands -pipe],
+ tcl_cv_cc_pipe, [
+ hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe"
+ AC_TRY_COMPILE(,, tcl_cv_cc_pipe=yes, tcl_cv_cc_pipe=no)
+ CFLAGS=$hold_cflags])
+ if test $tcl_cv_cc_pipe = yes; then
+ CFLAGS="$CFLAGS -pipe"
+ fi
+ fi
+
+ #--------------------------------------------------------------------
+ # Common compiler flag setup
+ #--------------------------------------------------------------------
+
+ AC_C_BIGENDIAN
+ if test "${TEA_PLATFORM}" = "unix" ; then
+ TEA_TCL_LINK_LIBS
+ TEA_MISSING_POSIX_HEADERS
+ # Let the user call this, because if it triggers, they will
+ # need a compat/strtod.c that is correct. Users can also
+ # use Tcl_GetDouble(FromObj) instead.
+ #TEA_BUGGY_STRTOD
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_MAKE_LIB --
+#
+# Generate a line that can be used to build a shared/unshared library
+# in a platform independent manner.
+#
+# Arguments:
+# none
+#
+# Requires:
+#
+# Results:
+#
+# Defines the following vars:
+# CFLAGS - Done late here to note disturb other AC macros
+# MAKE_LIB - Command to execute to build the Tcl library;
+# differs depending on whether or not Tcl is being
+# compiled as a shared library.
+# MAKE_SHARED_LIB Makefile rule for building a shared library
+# MAKE_STATIC_LIB Makefile rule for building a static library
+# MAKE_STUB_LIB Makefile rule for building a stub library
+# VC_MANIFEST_EMBED_DLL Makefile rule for embedded VC manifest in DLL
+# VC_MANIFEST_EMBED_EXE Makefile rule for embedded VC manifest in EXE
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_MAKE_LIB], [
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then
+ MAKE_STATIC_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} \${SHLIB_LD_LIBS} \${LDFLAGS_DEFAULT} -out:\[$]@ \$(PKG_OBJECTS)"
+ AC_EGREP_CPP([manifest needed], [
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+print("manifest needed")
+#endif
+ ], [
+ # Could do a CHECK_PROG for mt, but should always be with MSVC8+
+ VC_MANIFEST_EMBED_DLL="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;2 ; fi"
+ VC_MANIFEST_EMBED_EXE="if test -f \[$]@.manifest ; then mt.exe -nologo -manifest \[$]@.manifest -outputresource:\[$]@\;1 ; fi"
+ MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}"
+ TEA_ADD_CLEANFILES([*.manifest])
+ ])
+ MAKE_STUB_LIB="\${STLIB_LD} -out:\[$]@ \$(PKG_STUB_OBJECTS)"
+ else
+ MAKE_STATIC_LIB="\${STLIB_LD} \[$]@ \$(PKG_OBJECTS)"
+ MAKE_SHARED_LIB="\${SHLIB_LD} -o \[$]@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}"
+ MAKE_STUB_LIB="\${STLIB_LD} \[$]@ \$(PKG_STUB_OBJECTS)"
+ fi
+
+ if test "${SHARED_BUILD}" = "1" ; then
+ MAKE_LIB="${MAKE_SHARED_LIB} "
+ else
+ MAKE_LIB="${MAKE_STATIC_LIB} "
+ fi
+
+ #--------------------------------------------------------------------
+ # Shared libraries and static libraries have different names.
+ # Use the double eval to make sure any variables in the suffix is
+ # substituted. (@@@ Might not be necessary anymore)
+ #--------------------------------------------------------------------
+
+ if test "${TEA_PLATFORM}" = "windows" ; then
+ if test "${SHARED_BUILD}" = "1" ; then
+ # We force the unresolved linking of symbols that are really in
+ # the private libraries of Tcl and Tk.
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\""
+ if test x"${TK_BIN_DIR}" != x ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\""
+ fi
+ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ else
+ eval eval "PKG_LIB_FILE=${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+ fi
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ if test "$GCC" = "yes"; then
+ PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE}
+ fi
+ # These aren't needed on Windows (either MSVC or gcc)
+ RANLIB=:
+ RANLIB_STUB=:
+ else
+ RANLIB_STUB="${RANLIB}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}"
+ if test x"${TK_BIN_DIR}" != x ; then
+ SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}"
+ fi
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${SHARED_LIB_SUFFIX}"
+ RANLIB=:
+ else
+ eval eval "PKG_LIB_FILE=lib${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}"
+ fi
+ # Some packages build their own stubs libraries
+ eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}"
+ fi
+
+ # These are escaped so that only CFLAGS is picked up at configure time.
+ # The other values will be substituted at make time.
+ CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}"
+ if test "${SHARED_BUILD}" = "1" ; then
+ CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}"
+ fi
+
+ AC_SUBST(MAKE_LIB)
+ AC_SUBST(MAKE_SHARED_LIB)
+ AC_SUBST(MAKE_STATIC_LIB)
+ AC_SUBST(MAKE_STUB_LIB)
+ AC_SUBST(RANLIB_STUB)
+ AC_SUBST(VC_MANIFEST_EMBED_DLL)
+ AC_SUBST(VC_MANIFEST_EMBED_EXE)
+])
+
+#------------------------------------------------------------------------
+# TEA_LIB_SPEC --
+#
+# Compute the name of an existing object library located in libdir
+# from the given base name and produce the appropriate linker flags.
+#
+# Arguments:
+# basename The base name of the library without version
+# numbers, extensions, or "lib" prefixes.
+# extra_dir Extra directory in which to search for the
+# library. This location is used first, then
+# $prefix/$exec-prefix, then some defaults.
+#
+# Requires:
+# TEA_INIT and TEA_PREFIX must be called first.
+#
+# Results:
+#
+# Defines the following vars:
+# ${basename}_LIB_NAME The computed library name.
+# ${basename}_LIB_SPEC The computed linker flags.
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_LIB_SPEC], [
+ AC_MSG_CHECKING([for $1 library])
+
+ # Look in exec-prefix for the library (defined by TEA_PREFIX).
+
+ tea_lib_name_dir="${exec_prefix}/lib"
+
+ # Or in a user-specified location.
+
+ if test x"$2" != x ; then
+ tea_extra_lib_dir=$2
+ else
+ tea_extra_lib_dir=NONE
+ fi
+
+ for i in \
+ `ls -dr ${tea_extra_lib_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
+ `ls -dr ${tea_extra_lib_dir}/lib$1[[0-9]]* 2>/dev/null ` \
+ `ls -dr ${tea_lib_name_dir}/$1[[0-9]]*.lib 2>/dev/null ` \
+ `ls -dr ${tea_lib_name_dir}/lib$1[[0-9]]* 2>/dev/null ` \
+ `ls -dr /usr/lib/$1[[0-9]]*.lib 2>/dev/null ` \
+ `ls -dr /usr/lib/lib$1[[0-9]]* 2>/dev/null ` \
+ `ls -dr /usr/lib64/$1[[0-9]]*.lib 2>/dev/null ` \
+ `ls -dr /usr/lib64/lib$1[[0-9]]* 2>/dev/null ` \
+ `ls -dr /usr/local/lib/$1[[0-9]]*.lib 2>/dev/null ` \
+ `ls -dr /usr/local/lib/lib$1[[0-9]]* 2>/dev/null ` ; do
+ if test -f "$i" ; then
+ tea_lib_name_dir=`dirname $i`
+ $1_LIB_NAME=`basename $i`
+ $1_LIB_PATH_NAME=$i
+ break
+ fi
+ done
+
+ if test "${TEA_PLATFORM}" = "windows"; then
+ $1_LIB_SPEC=\"`${CYGPATH} ${$1_LIB_PATH_NAME} 2>/dev/null`\"
+ else
+ # Strip off the leading "lib" and trailing ".a" or ".so"
+
+ tea_lib_name_lib=`echo ${$1_LIB_NAME}|sed -e 's/^lib//' -e 's/\.[[^.]]*$//' -e 's/\.so.*//'`
+ $1_LIB_SPEC="-L${tea_lib_name_dir} -l${tea_lib_name_lib}"
+ fi
+
+ if test "x${$1_LIB_NAME}" = x ; then
+ AC_MSG_ERROR([not found])
+ else
+ AC_MSG_RESULT([${$1_LIB_SPEC}])
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PRIVATE_TCL_HEADERS --
+#
+# Locate the private Tcl include files
+#
+# Arguments:
+#
+# Requires:
+# TCL_SRC_DIR Assumes that TEA_LOAD_TCLCONFIG has
+# already been called.
+#
+# Results:
+#
+# Substitutes the following vars:
+# TCL_TOP_DIR_NATIVE
+# TCL_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PRIVATE_TCL_HEADERS], [
+ # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh}
+ AC_REQUIRE([TEA_PUBLIC_TCL_HEADERS])
+ AC_MSG_CHECKING([for Tcl private include files])
+
+ TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}`
+ TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\"
+
+ # Check to see if tcl<Plat>Port.h isn't already with the public headers
+ # Don't look for tclInt.h because that resides with tcl.h in the core
+ # sources, but the <plat>Port headers are in a different directory
+ if test "${TEA_PLATFORM}" = "windows" -a \
+ -f "${ac_cv_c_tclh}/tclWinPort.h"; then
+ result="private headers found with public headers"
+ elif test "${TEA_PLATFORM}" = "unix" -a \
+ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then
+ result="private headers found with public headers"
+ else
+ TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\"
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\"
+ else
+ TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\"
+ fi
+ # Overwrite the previous TCL_INCLUDES as this should capture both
+ # public and private headers in the same set.
+ # We want to ensure these are substituted so as not to require
+ # any *_NATIVE vars be defined in the Makefile
+ TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}"
+ if test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use
+ # the framework's Headers and PrivateHeaders directories
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ if test -d "${TCL_BIN_DIR}/Headers" -a \
+ -d "${TCL_BIN_DIR}/PrivateHeaders"; then
+ TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}"
+ else
+ TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
+ fi
+ ;;
+ esac
+ result="Using ${TCL_INCLUDES}"
+ else
+ if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then
+ AC_MSG_ERROR([Cannot find private header tclInt.h in ${TCL_SRC_DIR}])
+ fi
+ result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}"
+ fi
+ fi
+
+ AC_SUBST(TCL_TOP_DIR_NATIVE)
+
+ AC_SUBST(TCL_INCLUDES)
+ AC_MSG_RESULT([${result}])
+])
+
+#------------------------------------------------------------------------
+# TEA_PUBLIC_TCL_HEADERS --
+#
+# Locate the installed public Tcl header files
+#
+# Arguments:
+# None.
+#
+# Requires:
+# CYGPATH must be set
+#
+# Results:
+#
+# Adds a --with-tclinclude switch to configure.
+# Result is cached.
+#
+# Substitutes the following vars:
+# TCL_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PUBLIC_TCL_HEADERS], [
+ AC_MSG_CHECKING([for Tcl public headers])
+
+ AC_ARG_WITH(tclinclude, [ --with-tclinclude directory containing the public Tcl header files], with_tclinclude=${withval})
+
+ AC_CACHE_VAL(ac_cv_c_tclh, [
+ # Use the value from --with-tclinclude, if it was given
+
+ if test x"${with_tclinclude}" != x ; then
+ if test -f "${with_tclinclude}/tcl.h" ; then
+ ac_cv_c_tclh=${with_tclinclude}
+ else
+ AC_MSG_ERROR([${with_tclinclude} directory does not contain tcl.h])
+ fi
+ else
+ list=""
+ if test "`uname -s`" = "Darwin"; then
+ # If Tcl was built as a framework, attempt to use
+ # the framework's Headers directory
+ case ${TCL_DEFS} in
+ *TCL_FRAMEWORK*)
+ list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`"
+ ;;
+ esac
+ fi
+
+ # Look in the source dir only if Tcl is not installed,
+ # and in that situation, look there before installed locations.
+ if test -f "${TCL_BIN_DIR}/Makefile" ; then
+ list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`"
+ fi
+
+ # Check order: pkg --prefix location, Tcl's --prefix location,
+ # relative to directory of tclConfig.sh.
+
+ eval "temp_includedir=${includedir}"
+ list="$list \
+ `ls -d ${temp_includedir} 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
+ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+ list="$list /usr/local/include /usr/include"
+ if test x"${TCL_INCLUDE_SPEC}" != x ; then
+ d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'`
+ list="$list `ls -d ${d} 2>/dev/null`"
+ fi
+ fi
+ for i in $list ; do
+ if test -f "$i/tcl.h" ; then
+ ac_cv_c_tclh=$i
+ break
+ fi
+ done
+ fi
+ ])
+
+ # Print a message based on how we determined the include path
+
+ if test x"${ac_cv_c_tclh}" = x ; then
+ AC_MSG_ERROR([tcl.h not found. Please specify its location with --with-tclinclude])
+ else
+ AC_MSG_RESULT([${ac_cv_c_tclh}])
+ fi
+
+ # Convert to a native path and substitute into the output files.
+
+ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}`
+
+ TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+ AC_SUBST(TCL_INCLUDES)
+])
+
+#------------------------------------------------------------------------
+# TEA_PRIVATE_TK_HEADERS --
+#
+# Locate the private Tk include files
+#
+# Arguments:
+#
+# Requires:
+# TK_SRC_DIR Assumes that TEA_LOAD_TKCONFIG has
+# already been called.
+#
+# Results:
+#
+# Substitutes the following vars:
+# TK_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PRIVATE_TK_HEADERS], [
+ # Allow for --with-tkinclude to take effect and define ${ac_cv_c_tkh}
+ AC_REQUIRE([TEA_PUBLIC_TK_HEADERS])
+ AC_MSG_CHECKING([for Tk private include files])
+
+ TK_SRC_DIR_NATIVE=`${CYGPATH} ${TK_SRC_DIR}`
+ TK_TOP_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}\"
+
+ # Check to see if tk<Plat>Port.h isn't already with the public headers
+ # Don't look for tkInt.h because that resides with tk.h in the core
+ # sources, but the <plat>Port headers are in a different directory
+ if test "${TEA_PLATFORM}" = "windows" -a \
+ -f "${ac_cv_c_tkh}/tkWinPort.h"; then
+ result="private headers found with public headers"
+ elif test "${TEA_PLATFORM}" = "unix" -a \
+ -f "${ac_cv_c_tkh}/tkUnixPort.h"; then
+ result="private headers found with public headers"
+ else
+ TK_GENERIC_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/generic\"
+ TK_XLIB_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/xlib\"
+ if test "${TEA_PLATFORM}" = "windows"; then
+ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/win\"
+ else
+ TK_PLATFORM_DIR_NATIVE=\"${TK_SRC_DIR_NATIVE}/unix\"
+ fi
+ # Overwrite the previous TK_INCLUDES as this should capture both
+ # public and private headers in the same set.
+ # We want to ensure these are substituted so as not to require
+ # any *_NATIVE vars be defined in the Makefile
+ TK_INCLUDES="-I${TK_GENERIC_DIR_NATIVE} -I${TK_PLATFORM_DIR_NATIVE}"
+ # Detect and add ttk subdir
+ if test -d "${TK_SRC_DIR}/generic/ttk"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/generic/ttk\""
+ fi
+ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_XLIB_DIR_NATIVE}\""
+ fi
+ if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then
+ TK_INCLUDES="${TK_INCLUDES} -I\"${TK_SRC_DIR_NATIVE}/macosx\""
+ fi
+ if test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use
+ # the framework's Headers and PrivateHeaders directories
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ if test -d "${TK_BIN_DIR}/Headers" -a \
+ -d "${TK_BIN_DIR}/PrivateHeaders"; then
+ TK_INCLUDES="-I\"${TK_BIN_DIR}/Headers\" -I\"${TK_BIN_DIR}/PrivateHeaders\" ${TK_INCLUDES}"
+ else
+ TK_INCLUDES="${TK_INCLUDES} ${TK_INCLUDE_SPEC} `echo "${TK_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`"
+ fi
+ ;;
+ esac
+ result="Using ${TK_INCLUDES}"
+ else
+ if test ! -f "${TK_SRC_DIR}/generic/tkInt.h" ; then
+ AC_MSG_ERROR([Cannot find private header tkInt.h in ${TK_SRC_DIR}])
+ fi
+ result="Using srcdir found in tkConfig.sh: ${TK_SRC_DIR}"
+ fi
+ fi
+
+ AC_SUBST(TK_TOP_DIR_NATIVE)
+ AC_SUBST(TK_XLIB_DIR_NATIVE)
+
+ AC_SUBST(TK_INCLUDES)
+ AC_MSG_RESULT([${result}])
+])
+
+#------------------------------------------------------------------------
+# TEA_PUBLIC_TK_HEADERS --
+#
+# Locate the installed public Tk header files
+#
+# Arguments:
+# None.
+#
+# Requires:
+# CYGPATH must be set
+#
+# Results:
+#
+# Adds a --with-tkinclude switch to configure.
+# Result is cached.
+#
+# Substitutes the following vars:
+# TK_INCLUDES
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PUBLIC_TK_HEADERS], [
+ AC_MSG_CHECKING([for Tk public headers])
+
+ AC_ARG_WITH(tkinclude, [ --with-tkinclude directory containing the public Tk header files], with_tkinclude=${withval})
+
+ AC_CACHE_VAL(ac_cv_c_tkh, [
+ # Use the value from --with-tkinclude, if it was given
+
+ if test x"${with_tkinclude}" != x ; then
+ if test -f "${with_tkinclude}/tk.h" ; then
+ ac_cv_c_tkh=${with_tkinclude}
+ else
+ AC_MSG_ERROR([${with_tkinclude} directory does not contain tk.h])
+ fi
+ else
+ list=""
+ if test "`uname -s`" = "Darwin"; then
+ # If Tk was built as a framework, attempt to use
+ # the framework's Headers directory.
+ case ${TK_DEFS} in
+ *TK_FRAMEWORK*)
+ list="`ls -d ${TK_BIN_DIR}/Headers 2>/dev/null`"
+ ;;
+ esac
+ fi
+
+ # Look in the source dir only if Tk is not installed,
+ # and in that situation, look there before installed locations.
+ if test -f "${TK_BIN_DIR}/Makefile" ; then
+ list="$list `ls -d ${TK_SRC_DIR}/generic 2>/dev/null`"
+ fi
+
+ # Check order: pkg --prefix location, Tk's --prefix location,
+ # relative to directory of tkConfig.sh, Tcl's --prefix location,
+ # relative to directory of tclConfig.sh.
+
+ eval "temp_includedir=${includedir}"
+ list="$list \
+ `ls -d ${temp_includedir} 2>/dev/null` \
+ `ls -d ${TK_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TK_BIN_DIR}/../include 2>/dev/null` \
+ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \
+ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`"
+ if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then
+ list="$list /usr/local/include /usr/include"
+ if test x"${TK_INCLUDE_SPEC}" != x ; then
+ d=`echo "${TK_INCLUDE_SPEC}" | sed -e 's/^-I//'`
+ list="$list `ls -d ${d} 2>/dev/null`"
+ fi
+ fi
+ for i in $list ; do
+ if test -f "$i/tk.h" ; then
+ ac_cv_c_tkh=$i
+ break
+ fi
+ done
+ fi
+ ])
+
+ # Print a message based on how we determined the include path
+
+ if test x"${ac_cv_c_tkh}" = x ; then
+ AC_MSG_ERROR([tk.h not found. Please specify its location with --with-tkinclude])
+ else
+ AC_MSG_RESULT([${ac_cv_c_tkh}])
+ fi
+
+ # Convert to a native path and substitute into the output files.
+
+ INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tkh}`
+
+ TK_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+
+ AC_SUBST(TK_INCLUDES)
+
+ if test "${TEA_WINDOWINGSYSTEM}" != "x11"; then
+ # On Windows and Aqua, we need the X compat headers
+ AC_MSG_CHECKING([for X11 header files])
+ if test ! -r "${INCLUDE_DIR_NATIVE}/X11/Xlib.h"; then
+ INCLUDE_DIR_NATIVE="`${CYGPATH} ${TK_SRC_DIR}/xlib`"
+ TK_XINCLUDES=-I\"${INCLUDE_DIR_NATIVE}\"
+ AC_SUBST(TK_XINCLUDES)
+ fi
+ AC_MSG_RESULT([${INCLUDE_DIR_NATIVE}])
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_PATH_CONFIG --
+#
+# Locate the ${1}Config.sh file and perform a sanity check on
+# the ${1} compile flags. These are used by packages like
+# [incr Tk] that load *Config.sh files from more than Tcl and Tk.
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-$1=...
+#
+# Defines the following vars:
+# $1_BIN_DIR Full path to the directory containing
+# the $1Config.sh file
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_CONFIG], [
+ #
+ # Ok, lets find the $1 configuration
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-$1
+ #
+
+ if test x"${no_$1}" = x ; then
+ # we reset no_$1 in case something fails here
+ no_$1=true
+ AC_ARG_WITH($1, [ --with-$1 directory containing $1 configuration ($1Config.sh)], with_$1config=${withval})
+ AC_MSG_CHECKING([for $1 configuration])
+ AC_CACHE_VAL(ac_cv_c_$1config,[
+
+ # First check to see if --with-$1 was specified.
+ if test x"${with_$1config}" != x ; then
+ case ${with_$1config} in
+ */$1Config.sh )
+ if test -f ${with_$1config}; then
+ AC_MSG_WARN([--with-$1 argument should refer to directory containing $1Config.sh, not to $1Config.sh itself])
+ with_$1config=`echo ${with_$1config} | sed 's!/$1Config\.sh$!!'`
+ fi;;
+ esac
+ if test -f "${with_$1config}/$1Config.sh" ; then
+ ac_cv_c_$1config=`(cd ${with_$1config}; pwd)`
+ else
+ AC_MSG_ERROR([${with_$1config} directory doesn't contain $1Config.sh])
+ fi
+ fi
+
+ # then check for a private $1 installation
+ if test x"${ac_cv_c_$1config}" = x ; then
+ for i in \
+ ../$1 \
+ `ls -dr ../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+ `ls -dr ../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+ `ls -dr ../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+ ../../$1 \
+ `ls -dr ../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+ `ls -dr ../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+ ../../../$1 \
+ `ls -dr ../../../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+ `ls -dr ../../../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+ `ls -dr ../../../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ../../../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../$1 \
+ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]*.[[0-9]]* 2>/dev/null` \
+ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]][[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]] 2>/dev/null` \
+ `ls -dr ${srcdir}/../$1*[[0-9]].[[0-9]]* 2>/dev/null` \
+ ; do
+ if test -f "$i/$1Config.sh" ; then
+ ac_cv_c_$1config=`(cd $i; pwd)`
+ break
+ fi
+ if test -f "$i/unix/$1Config.sh" ; then
+ ac_cv_c_$1config=`(cd $i/unix; pwd)`
+ break
+ fi
+ done
+ fi
+
+ # check in a few common install locations
+ if test x"${ac_cv_c_$1config}" = x ; then
+ for i in `ls -d ${libdir} 2>/dev/null` \
+ `ls -d ${exec_prefix}/lib 2>/dev/null` \
+ `ls -d ${prefix}/lib 2>/dev/null` \
+ `ls -d /usr/local/lib 2>/dev/null` \
+ `ls -d /usr/contrib/lib 2>/dev/null` \
+ `ls -d /usr/lib 2>/dev/null` \
+ `ls -d /usr/lib64 2>/dev/null` \
+ ; do
+ if test -f "$i/$1Config.sh" ; then
+ ac_cv_c_$1config=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+
+ if test x"${ac_cv_c_$1config}" = x ; then
+ $1_BIN_DIR="# no $1 configs found"
+ AC_MSG_WARN([Cannot find $1 configuration definitions])
+ exit 0
+ else
+ no_$1=
+ $1_BIN_DIR=${ac_cv_c_$1config}
+ AC_MSG_RESULT([found $$1_BIN_DIR/$1Config.sh])
+ fi
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_CONFIG --
+#
+# Load the $1Config.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# $1_BIN_DIR
+#
+# Results:
+#
+# Substitutes the following vars:
+# $1_SRC_DIR
+# $1_LIB_FILE
+# $1_LIB_SPEC
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_LOAD_CONFIG], [
+ AC_MSG_CHECKING([for existence of ${$1_BIN_DIR}/$1Config.sh])
+
+ if test -f "${$1_BIN_DIR}/$1Config.sh" ; then
+ AC_MSG_RESULT([loading])
+ . "${$1_BIN_DIR}/$1Config.sh"
+ else
+ AC_MSG_RESULT([file not found])
+ fi
+
+ #
+ # If the $1_BIN_DIR is the build directory (not the install directory),
+ # then set the common variable name to the value of the build variables.
+ # For example, the variable $1_LIB_SPEC will be set to the value
+ # of $1_BUILD_LIB_SPEC. An extension should make use of $1_LIB_SPEC
+ # instead of $1_BUILD_LIB_SPEC since it will work with both an
+ # installed and uninstalled version of Tcl.
+ #
+
+ if test -f "${$1_BIN_DIR}/Makefile" ; then
+ AC_MSG_WARN([Found Makefile - using build library specs for $1])
+ $1_LIB_SPEC=${$1_BUILD_LIB_SPEC}
+ $1_STUB_LIB_SPEC=${$1_BUILD_STUB_LIB_SPEC}
+ $1_STUB_LIB_PATH=${$1_BUILD_STUB_LIB_PATH}
+ $1_INCLUDE_SPEC=${$1_BUILD_INCLUDE_SPEC}
+ $1_LIBRARY_PATH=${$1_LIBRARY_PATH}
+ fi
+
+ AC_SUBST($1_VERSION)
+ AC_SUBST($1_BIN_DIR)
+ AC_SUBST($1_SRC_DIR)
+
+ AC_SUBST($1_LIB_FILE)
+ AC_SUBST($1_LIB_SPEC)
+
+ AC_SUBST($1_STUB_LIB_FILE)
+ AC_SUBST($1_STUB_LIB_SPEC)
+ AC_SUBST($1_STUB_LIB_PATH)
+
+ # Allow the caller to prevent this auto-check by specifying any 2nd arg
+ AS_IF([test "x$2" = x], [
+ # Check both upper and lower-case variants
+ # If a dev wanted non-stubs libs, this function could take an option
+ # to not use _STUB in the paths below
+ AS_IF([test "x${$1_STUB_LIB_SPEC}" = x],
+ [TEA_LOAD_CONFIG_LIB(translit($1,[a-z],[A-Z])_STUB)],
+ [TEA_LOAD_CONFIG_LIB($1_STUB)])
+ ])
+])
+
+#------------------------------------------------------------------------
+# TEA_LOAD_CONFIG_LIB --
+#
+# Helper function to load correct library from another extension's
+# ${PACKAGE}Config.sh.
+#
+# Results:
+# Adds to LIBS the appropriate extension library
+#------------------------------------------------------------------------
+AC_DEFUN([TEA_LOAD_CONFIG_LIB], [
+ AC_MSG_CHECKING([For $1 library for LIBS])
+ # This simplifies the use of stub libraries by automatically adding
+ # the stub lib to your path. Normally this would add to SHLIB_LD_LIBS,
+ # but this is called before CONFIG_CFLAGS. More importantly, this adds
+ # to PKG_LIBS, which becomes LIBS, and that is only used by SHLIB_LD.
+ if test "x${$1_LIB_SPEC}" != "x" ; then
+ if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes" ; then
+ TEA_ADD_LIBS([\"`${CYGPATH} ${$1_LIB_PATH}`\"])
+ AC_MSG_RESULT([using $1_LIB_PATH ${$1_LIB_PATH}])
+ else
+ TEA_ADD_LIBS([${$1_LIB_SPEC}])
+ AC_MSG_RESULT([using $1_LIB_SPEC ${$1_LIB_SPEC}])
+ fi
+ else
+ AC_MSG_RESULT([file not found])
+ fi
+])
+
+#------------------------------------------------------------------------
+# TEA_EXPORT_CONFIG --
+#
+# Define the data to insert into the ${PACKAGE}Config.sh file
+#
+# Arguments:
+#
+# Requires the following vars to be set:
+# $1
+#
+# Results:
+# Substitutes the following vars:
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_EXPORT_CONFIG], [
+ #--------------------------------------------------------------------
+ # These are for $1Config.sh
+ #--------------------------------------------------------------------
+
+ # pkglibdir must be a fully qualified path and (not ${exec_prefix}/lib)
+ eval pkglibdir="[$]{libdir}/$1${PACKAGE_VERSION}"
+ if test "${TCL_LIB_VERSIONS_OK}" = "ok"; then
+ eval $1_LIB_FLAG="-l$1${PACKAGE_VERSION}${DBGX}"
+ eval $1_STUB_LIB_FLAG="-l$1stub${PACKAGE_VERSION}${DBGX}"
+ else
+ eval $1_LIB_FLAG="-l$1`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
+ eval $1_STUB_LIB_FLAG="-l$1stub`echo ${PACKAGE_VERSION} | tr -d .`${DBGX}"
+ fi
+ $1_BUILD_LIB_SPEC="-L`pwd` ${$1_LIB_FLAG}"
+ $1_LIB_SPEC="-L${pkglibdir} ${$1_LIB_FLAG}"
+ $1_BUILD_STUB_LIB_SPEC="-L`pwd` [$]{$1_STUB_LIB_FLAG}"
+ $1_STUB_LIB_SPEC="-L${pkglibdir} [$]{$1_STUB_LIB_FLAG}"
+ $1_BUILD_STUB_LIB_PATH="`pwd`/[$]{PKG_STUB_LIB_FILE}"
+ $1_STUB_LIB_PATH="${pkglibdir}/[$]{PKG_STUB_LIB_FILE}"
+
+ AC_SUBST($1_BUILD_LIB_SPEC)
+ AC_SUBST($1_LIB_SPEC)
+ AC_SUBST($1_BUILD_STUB_LIB_SPEC)
+ AC_SUBST($1_STUB_LIB_SPEC)
+ AC_SUBST($1_BUILD_STUB_LIB_PATH)
+ AC_SUBST($1_STUB_LIB_PATH)
+
+ AC_SUBST(MAJOR_VERSION)
+ AC_SUBST(MINOR_VERSION)
+ AC_SUBST(PATCHLEVEL)
+])
+
+
+#------------------------------------------------------------------------
+# TEA_PATH_CELIB --
+#
+# Locate Keuchel's celib emulation layer for targeting Win/CE
+#
+# Arguments:
+# none
+#
+# Results:
+#
+# Adds the following arguments to configure:
+# --with-celib=...
+#
+# Defines the following vars:
+# CELIB_DIR Full path to the directory containing
+# the include and platform lib files
+#------------------------------------------------------------------------
+
+AC_DEFUN([TEA_PATH_CELIB], [
+ # First, look for one uninstalled.
+ # the alternative search directory is invoked by --with-celib
+
+ if test x"${no_celib}" = x ; then
+ # we reset no_celib in case something fails here
+ no_celib=true
+ AC_ARG_WITH(celib,[ --with-celib=DIR use Windows/CE support library from DIR], with_celibconfig=${withval})
+ AC_MSG_CHECKING([for Windows/CE celib directory])
+ AC_CACHE_VAL(ac_cv_c_celibconfig,[
+ # First check to see if --with-celibconfig was specified.
+ if test x"${with_celibconfig}" != x ; then
+ if test -d "${with_celibconfig}/inc" ; then
+ ac_cv_c_celibconfig=`(cd ${with_celibconfig}; pwd)`
+ else
+ AC_MSG_ERROR([${with_celibconfig} directory doesn't contain inc directory])
+ fi
+ fi
+
+ # then check for a celib library
+ if test x"${ac_cv_c_celibconfig}" = x ; then
+ for i in \
+ ../celib-palm-3.0 \
+ ../celib \
+ ../../celib-palm-3.0 \
+ ../../celib \
+ `ls -dr ../celib-*3.[[0-9]]* 2>/dev/null` \
+ ${srcdir}/../celib-palm-3.0 \
+ ${srcdir}/../celib \
+ `ls -dr ${srcdir}/../celib-*3.[[0-9]]* 2>/dev/null` \
+ ; do
+ if test -d "$i/inc" ; then
+ ac_cv_c_celibconfig=`(cd $i; pwd)`
+ break
+ fi
+ done
+ fi
+ ])
+ if test x"${ac_cv_c_celibconfig}" = x ; then
+ AC_MSG_ERROR([Cannot find celib support library directory])
+ else
+ no_celib=
+ CELIB_DIR=${ac_cv_c_celibconfig}
+ CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'`
+ AC_MSG_RESULT([found $CELIB_DIR])
+ fi
+ fi
+])
+
+
+# Local Variables:
+# mode: autoconf
+# End:
diff --git a/unix/Makefile b/unix/Makefile
index 321e17c..1c7f263 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -32,12 +32,3 @@ distclean : clean
rm -f *.o *.so *.a
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
diff --git a/unix/rotstr.C b/unix/rotstr.C
index 8ba3cc0..e1996ee 100644
--- a/unix/rotstr.C
+++ b/unix/rotstr.C
@@ -2,12 +2,12 @@
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"
+#include <X11/Xutil.h>
+
#include "rotstr.h"
#include "vector.h"
#include "widget.h"
-#include <tk.h>
-#include <X11/Xutil.h>
void XDrawRotString(Display* display, Drawable drawable, GC gc,
Vector& v, double angle, const char* text,
diff --git a/unix/rotstr.h b/unix/rotstr.h
index 5623831..1e44482 100644
--- a/unix/rotstr.h
+++ b/unix/rotstr.h
@@ -10,6 +10,6 @@
class Widget;
class Vector;
extern void XDrawRotString(Display* display, Drawable drawable, GC gc,
- Vector&, double angle, const char* text,
+ Vector& v, double angle, const char* text,
Tk_Font font, Widget* parent);
#endif
diff --git a/win/Makefile b/win/Makefile
index 512febf..aee4c5b 100644
--- a/win/Makefile
+++ b/win/Makefile
@@ -4,8 +4,10 @@ include ../make.pkgs
# no ./configure
CXXFLAGS = $(CXXOPT) \
-I../include \
- -I../$(TKDIR)/generic -I../$(TKDIR)/win \
+ -I../$(TCLDIR)/generic \
+ -I../$(TKDIR)/generic \
-I../saotk/vector \
+ -I../$(TKDIR)/win \
-I$(X11INCLUDE)
SRC = rotstr.C \
@@ -35,12 +37,3 @@ distclean : clean
rm -f *.o *.so *.a
FORCE :
-
-ifdef DEPENDS
-%.d: %.C
- set -e; $(CXX) -MM $(CXXFLAGS) $< \
- | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
- [ -s $@ ] || rm -f $@
-
-include $(SRC:.C=.d)
-endif
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/saods9.git
More information about the debian-science-commits
mailing list